[hal] Merge WaitForCachedData into WaitForDSData (#2587)

Remove WaitForCachedData as it's no longer required.

Also properly handle caching / transition detection logic that occurs at the
WPILib level.

This also changes DriverStation::IsNewControlData() to check for WPILib-level
caching instead of wrapping the HAL function.
This commit is contained in:
Peter Johnson
2020-07-13 21:57:54 -07:00
committed by GitHub
parent f0a34ea64e
commit 16ef372b53
6 changed files with 86 additions and 120 deletions

View File

@@ -124,7 +124,7 @@ static int32_t HAL_GetMatchInfoInternal(HAL_MatchInfo* info) {
static wpi::mutex* newDSDataAvailableMutex;
static wpi::condition_variable* newDSDataAvailableCond;
static std::atomic_int newDSDataAvailableCounter{0};
static int newDSDataAvailableCounter{0};
namespace hal {
namespace init {
@@ -355,41 +355,14 @@ static int& GetThreadLocalLastCount() {
// will return false when instead it should return true. However, this at a
// 20ms rate occurs once every 2.7 years of DS connected runtime, so not
// worth the cycles to check.
thread_local int lastCount{-1};
thread_local int lastCount{0};
return lastCount;
}
void HAL_WaitForCachedControlData(void) {
HAL_WaitForCachedControlDataTimeout(0);
}
HAL_Bool HAL_WaitForCachedControlDataTimeout(double timeout) {
int& lastCount = GetThreadLocalLastCount();
int currentCount = newDSDataAvailableCounter.load();
if (lastCount != currentCount) {
lastCount = currentCount;
return true;
}
auto timeoutTime =
std::chrono::steady_clock::now() + std::chrono::duration<double>(timeout);
std::unique_lock lock{*newDSDataAvailableMutex};
while (newDSDataAvailableCounter.load() == currentCount) {
if (timeout > 0) {
auto timedOut = newDSDataAvailableCond->wait_until(lock, timeoutTime);
if (timedOut == std::cv_status::timeout) {
return false;
}
} else {
newDSDataAvailableCond->wait(lock);
}
}
return true;
}
HAL_Bool HAL_IsNewControlData(void) {
std::scoped_lock lock{*newDSDataAvailableMutex};
int& lastCount = GetThreadLocalLastCount();
int currentCount = newDSDataAvailableCounter.load();
int currentCount = newDSDataAvailableCounter;
if (lastCount == currentCount) return false;
lastCount = currentCount;
return true;
@@ -406,12 +379,17 @@ void HAL_WaitForDSData(void) { HAL_WaitForDSDataTimeout(0); }
* time has passed. Returns true on new data, false on timeout.
*/
HAL_Bool HAL_WaitForDSDataTimeout(double timeout) {
std::unique_lock lock{*newDSDataAvailableMutex};
int& lastCount = GetThreadLocalLastCount();
int currentCount = newDSDataAvailableCounter;
if (lastCount != currentCount) {
lastCount = currentCount;
return true;
}
auto timeoutTime =
std::chrono::steady_clock::now() + std::chrono::duration<double>(timeout);
int currentCount = newDSDataAvailableCounter.load();
std::unique_lock lock{*newDSDataAvailableMutex};
while (newDSDataAvailableCounter.load() == currentCount) {
while (newDSDataAvailableCounter == currentCount) {
if (timeout > 0) {
auto timedOut = newDSDataAvailableCond->wait_until(lock, timeoutTime);
if (timedOut == std::cv_status::timeout) {
@@ -421,6 +399,7 @@ HAL_Bool HAL_WaitForDSDataTimeout(double timeout) {
newDSDataAvailableCond->wait(lock);
}
}
lastCount = newDSDataAvailableCounter;
return true;
}
@@ -431,8 +410,9 @@ static void newDataOccur(uint32_t refNum) {
// Since we could get other values, require our specific handle
// to signal our threads
if (refNum != refNumber) return;
std::scoped_lock lock{*newDSDataAvailableMutex};
// Notify all threads
newDSDataAvailableCounter.fetch_add(1);
++newDSDataAvailableCounter;
newDSDataAvailableCond->notify_all();
}