AtomicValue use epicsAtomic if available
This commit is contained in:
+39
-2
@@ -21,6 +21,11 @@
|
||||
#include <osiSock.h>
|
||||
#include <epicsTime.h>
|
||||
#include <epicsThread.h>
|
||||
#include <epicsVersion.h>
|
||||
|
||||
#if defined(EPICS_VERSION_INT) && EPICS_VERSION_INT>=VERSION_INT(3,15,1,0)
|
||||
#include <epicsAtomic.h>
|
||||
#endif
|
||||
|
||||
#include <pv/byteBuffer.h>
|
||||
#include <pv/pvType.h>
|
||||
@@ -48,8 +53,39 @@ namespace epics {
|
||||
namespace pvAccess {
|
||||
namespace detail {
|
||||
|
||||
// TODO replace mutex with atomic (CAS) operations
|
||||
template<typename T>
|
||||
#if defined(EPICS_VERSION_INT) && EPICS_VERSION_INT>=VERSION_INT(3,15,1,0)
|
||||
template<typename T>
|
||||
class AtomicValue
|
||||
{
|
||||
T val;
|
||||
public:
|
||||
AtomicValue() :val(0) {}
|
||||
inline T getAndSet(T newval)
|
||||
{
|
||||
int oldval;
|
||||
// epicsAtomic doesn't have unconditional swap
|
||||
do {
|
||||
oldval = epics::atomic::get(val);
|
||||
}while(epics::atomic::compareAndSwap(val, oldval, newval)!=oldval);
|
||||
return oldval;
|
||||
}
|
||||
inline T get() { return epics::atomic::get(val); }
|
||||
};
|
||||
// treat bool as int
|
||||
template<>
|
||||
class AtomicValue<bool>
|
||||
{
|
||||
AtomicValue<int> realval;
|
||||
public:
|
||||
inline bool getAndSet(bool newval)
|
||||
{
|
||||
return this->realval.getAndSet(newval?1:0)!=0;
|
||||
}
|
||||
inline bool get() { return !!this->realval.get(); }
|
||||
};
|
||||
|
||||
#else
|
||||
template<typename T>
|
||||
class AtomicValue
|
||||
{
|
||||
public:
|
||||
@@ -69,6 +105,7 @@ namespace epics {
|
||||
T _value;
|
||||
epics::pvData::Mutex mutex;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
// TODO replace this queue with lock-free implementation
|
||||
|
||||
Reference in New Issue
Block a user