Change hal sim to use spinlocks (#1291)

This makes callback registration completely thread safe.

This patch also uses templates and macros to dramatically reduce the amount of
manual boilerplate.
This commit is contained in:
Peter Johnson
2018-09-03 16:08:07 -07:00
committed by GitHub
parent 67b1c85315
commit c0ff6198b3
65 changed files with 1305 additions and 7639 deletions

View File

@@ -7,7 +7,6 @@
#include "../PortsInternal.h"
#include "RelayDataInternal.h"
#include "mockdata/NotifyCallbackHelpers.h"
using namespace hal;
@@ -22,253 +21,33 @@ void InitializeRelayData() {
RelayData* hal::SimRelayData;
void RelayData::ResetData() {
m_initializedForward = false;
m_initializedForwardCallbacks = nullptr;
m_initializedReverse = false;
m_initializedReverseCallbacks = nullptr;
m_forward = false;
m_forwardCallbacks = nullptr;
m_reverse = false;
m_reverseCallbacks = nullptr;
}
int32_t RelayData::RegisterInitializedForwardCallback(
HAL_NotifyCallback callback, void* param, HAL_Bool initialNotify) {
// Must return -1 on a null callback for error handling
if (callback == nullptr) return -1;
int32_t newUid = 0;
{
std::lock_guard<wpi::mutex> lock(m_registerMutex);
m_initializedForwardCallbacks =
RegisterCallback(m_initializedForwardCallbacks, "InitializedForward",
callback, param, &newUid);
}
if (initialNotify) {
// We know that the callback is not null because of earlier null check
HAL_Value value = MakeBoolean(GetInitializedForward());
callback("InitializedForward", param, &value);
}
return newUid;
}
void RelayData::CancelInitializedForwardCallback(int32_t uid) {
m_initializedForwardCallbacks =
CancelCallback(m_initializedForwardCallbacks, uid);
}
void RelayData::InvokeInitializedForwardCallback(HAL_Value value) {
InvokeCallback(m_initializedForwardCallbacks, "InitializedForward", &value);
}
HAL_Bool RelayData::GetInitializedForward() { return m_initializedForward; }
void RelayData::SetInitializedForward(HAL_Bool initializedForward) {
HAL_Bool oldValue = m_initializedForward.exchange(initializedForward);
if (oldValue != initializedForward) {
InvokeInitializedForwardCallback(MakeBoolean(initializedForward));
}
}
int32_t RelayData::RegisterInitializedReverseCallback(
HAL_NotifyCallback callback, void* param, HAL_Bool initialNotify) {
// Must return -1 on a null callback for error handling
if (callback == nullptr) return -1;
int32_t newUid = 0;
{
std::lock_guard<wpi::mutex> lock(m_registerMutex);
m_initializedReverseCallbacks =
RegisterCallback(m_initializedReverseCallbacks, "InitializedReverse",
callback, param, &newUid);
}
if (initialNotify) {
// We know that the callback is not null because of earlier null check
HAL_Value value = MakeBoolean(GetInitializedReverse());
callback("InitializedReverse", param, &value);
}
return newUid;
}
void RelayData::CancelInitializedReverseCallback(int32_t uid) {
m_initializedReverseCallbacks =
CancelCallback(m_initializedReverseCallbacks, uid);
}
void RelayData::InvokeInitializedReverseCallback(HAL_Value value) {
InvokeCallback(m_initializedReverseCallbacks, "InitializedReverse", &value);
}
HAL_Bool RelayData::GetInitializedReverse() { return m_initializedReverse; }
void RelayData::SetInitializedReverse(HAL_Bool initializedReverse) {
HAL_Bool oldValue = m_initializedReverse.exchange(initializedReverse);
if (oldValue != initializedReverse) {
InvokeInitializedReverseCallback(MakeBoolean(initializedReverse));
}
}
int32_t RelayData::RegisterForwardCallback(HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify) {
// Must return -1 on a null callback for error handling
if (callback == nullptr) return -1;
int32_t newUid = 0;
{
std::lock_guard<wpi::mutex> lock(m_registerMutex);
m_forwardCallbacks = RegisterCallback(m_forwardCallbacks, "Forward",
callback, param, &newUid);
}
if (initialNotify) {
// We know that the callback is not null because of earlier null check
HAL_Value value = MakeBoolean(GetForward());
callback("Forward", param, &value);
}
return newUid;
}
void RelayData::CancelForwardCallback(int32_t uid) {
m_forwardCallbacks = CancelCallback(m_forwardCallbacks, uid);
}
void RelayData::InvokeForwardCallback(HAL_Value value) {
InvokeCallback(m_forwardCallbacks, "Forward", &value);
}
HAL_Bool RelayData::GetForward() { return m_forward; }
void RelayData::SetForward(HAL_Bool forward) {
HAL_Bool oldValue = m_forward.exchange(forward);
if (oldValue != forward) {
InvokeForwardCallback(MakeBoolean(forward));
}
}
int32_t RelayData::RegisterReverseCallback(HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify) {
// Must return -1 on a null callback for error handling
if (callback == nullptr) return -1;
int32_t newUid = 0;
{
std::lock_guard<wpi::mutex> lock(m_registerMutex);
m_reverseCallbacks = RegisterCallback(m_reverseCallbacks, "Reverse",
callback, param, &newUid);
}
if (initialNotify) {
// We know that the callback is not null because of earlier null check
HAL_Value value = MakeBoolean(GetReverse());
callback("Reverse", param, &value);
}
return newUid;
}
void RelayData::CancelReverseCallback(int32_t uid) {
m_reverseCallbacks = CancelCallback(m_reverseCallbacks, uid);
}
void RelayData::InvokeReverseCallback(HAL_Value value) {
InvokeCallback(m_reverseCallbacks, "Reverse", &value);
}
HAL_Bool RelayData::GetReverse() { return m_reverse; }
void RelayData::SetReverse(HAL_Bool reverse) {
HAL_Bool oldValue = m_reverse.exchange(reverse);
if (oldValue != reverse) {
InvokeReverseCallback(MakeBoolean(reverse));
}
initializedForward.Reset(false);
initializedReverse.Reset(false);
forward.Reset(false);
reverse.Reset(false);
}
extern "C" {
void HALSIM_ResetRelayData(int32_t index) { SimRelayData[index].ResetData(); }
int32_t HALSIM_RegisterRelayInitializedForwardCallback(
int32_t index, HAL_NotifyCallback callback, void* param,
HAL_Bool initialNotify) {
return SimRelayData[index].RegisterInitializedForwardCallback(callback, param,
initialNotify);
}
#define DEFINE_CAPI(TYPE, CAPINAME, LOWERNAME) \
HAL_SIMDATAVALUE_DEFINE_CAPI(TYPE, HALSIM, Relay##CAPINAME, SimRelayData, \
LOWERNAME)
void HALSIM_CancelRelayInitializedForwardCallback(int32_t index, int32_t uid) {
SimRelayData[index].CancelInitializedForwardCallback(uid);
}
DEFINE_CAPI(HAL_Bool, InitializedForward, initializedForward)
DEFINE_CAPI(HAL_Bool, InitializedReverse, initializedReverse)
DEFINE_CAPI(HAL_Bool, Forward, forward)
DEFINE_CAPI(HAL_Bool, Reverse, reverse)
HAL_Bool HALSIM_GetRelayInitializedForward(int32_t index) {
return SimRelayData[index].GetInitializedForward();
}
void HALSIM_SetRelayInitializedForward(int32_t index,
HAL_Bool initializedForward) {
SimRelayData[index].SetInitializedForward(initializedForward);
}
int32_t HALSIM_RegisterRelayInitializedReverseCallback(
int32_t index, HAL_NotifyCallback callback, void* param,
HAL_Bool initialNotify) {
return SimRelayData[index].RegisterInitializedReverseCallback(callback, param,
initialNotify);
}
void HALSIM_CancelRelayInitializedReverseCallback(int32_t index, int32_t uid) {
SimRelayData[index].CancelInitializedReverseCallback(uid);
}
HAL_Bool HALSIM_GetRelayInitializedReverse(int32_t index) {
return SimRelayData[index].GetInitializedReverse();
}
void HALSIM_SetRelayInitializedReverse(int32_t index,
HAL_Bool initializedReverse) {
SimRelayData[index].SetInitializedReverse(initializedReverse);
}
int32_t HALSIM_RegisterRelayForwardCallback(int32_t index,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify) {
return SimRelayData[index].RegisterForwardCallback(callback, param,
initialNotify);
}
void HALSIM_CancelRelayForwardCallback(int32_t index, int32_t uid) {
SimRelayData[index].CancelForwardCallback(uid);
}
HAL_Bool HALSIM_GetRelayForward(int32_t index) {
return SimRelayData[index].GetForward();
}
void HALSIM_SetRelayForward(int32_t index, HAL_Bool forward) {
SimRelayData[index].SetForward(forward);
}
int32_t HALSIM_RegisterRelayReverseCallback(int32_t index,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify) {
return SimRelayData[index].RegisterReverseCallback(callback, param,
initialNotify);
}
void HALSIM_CancelRelayReverseCallback(int32_t index, int32_t uid) {
SimRelayData[index].CancelReverseCallback(uid);
}
HAL_Bool HALSIM_GetRelayReverse(int32_t index) {
return SimRelayData[index].GetReverse();
}
void HALSIM_SetRelayReverse(int32_t index, HAL_Bool reverse) {
SimRelayData[index].SetReverse(reverse);
}
#define REGISTER(NAME) \
SimRelayData[index].NAME.RegisterCallback(callback, param, initialNotify)
void HALSIM_RegisterRelayAllCallbacks(int32_t index,
HAL_NotifyCallback callback, void* param,
HAL_Bool initialNotify) {
SimRelayData[index].RegisterInitializedForwardCallback(callback, param,
initialNotify);
SimRelayData[index].RegisterInitializedReverseCallback(callback, param,
initialNotify);
SimRelayData[index].RegisterForwardCallback(callback, param, initialNotify);
SimRelayData[index].RegisterReverseCallback(callback, param, initialNotify);
REGISTER(initializedForward);
REGISTER(initializedReverse);
REGISTER(forward);
REGISTER(reverse);
}
} // extern "C"