Changeset View
Changeset View
Standalone View
Standalone View
src/rcu.h
Show First 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | public: | ||||
} | } | ||||
static void synchronize() { RCUInfos::infos.synchronize(); } | static void synchronize() { RCUInfos::infos.synchronize(); } | ||||
}; | }; | ||||
template <typename T> class RCUPtr { | template <typename T> class RCUPtr { | ||||
T *ptr; | T *ptr; | ||||
// Private construction, so factories have to be used. | |||||
explicit RCUPtr(T *ptrIn) : ptr(ptrIn) {} | |||||
public: | public: | ||||
RCUPtr() : ptr(nullptr) {} | RCUPtr() : ptr(nullptr) {} | ||||
explicit RCUPtr(T *ptrIn) : ptr(ptrIn) {} | |||||
~RCUPtr() { | ~RCUPtr() { | ||||
if (ptr != nullptr) { | if (ptr != nullptr) { | ||||
ptr->release(); | ptr->release(); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Acquire ownership of some pointer. | |||||
*/ | |||||
static RCUPtr acquire(T *&ptrIn) { | |||||
RCUPtr ret(ptrIn); | |||||
ptrIn = nullptr; | |||||
return ret; | |||||
} | |||||
/** | |||||
* Construct a new object that is owned by the pointer. | * Construct a new object that is owned by the pointer. | ||||
*/ | */ | ||||
template <typename... Args> static RCUPtr make(Args &&... args) { | template <typename... Args> static RCUPtr make(Args &&... args) { | ||||
return RCUPtr(new T(std::forward<Args>(args)...)); | return RCUPtr(new T(std::forward<Args>(args)...)); | ||||
} | } | ||||
/** | /** | ||||
* Construct a new RCUPtr without transfering owership. | |||||
*/ | |||||
static RCUPtr copy(T *ptr) { | |||||
if (ptr != nullptr) { | |||||
ptr->acquire(); | |||||
} | |||||
return RCUPtr::acquire(ptr); | |||||
} | |||||
/** | |||||
* Copy semantic. | * Copy semantic. | ||||
*/ | */ | ||||
RCUPtr(const RCUPtr &src) : ptr(src.ptr) { | RCUPtr(const RCUPtr &src) : ptr(src.ptr) { | ||||
if (ptr != nullptr) { | if (ptr != nullptr) { | ||||
ptr->acquire(); | ptr->acquire(); | ||||
} | } | ||||
} | } | ||||
RCUPtr &operator=(const RCUPtr &rhs) { | RCUPtr &operator=(const RCUPtr &rhs) { | ||||
RCUPtr tmp(rhs); | RCUPtr tmp(rhs); | ||||
std::swap(ptr, tmp.ptr); | std::swap(ptr, tmp.ptr); | ||||
return *this; | return *this; | ||||
} | } | ||||
/** | /** | ||||
* Move semantic. | * Move semantic. | ||||
*/ | */ | ||||
RCUPtr(RCUPtr &&src) : RCUPtr() { std::swap(ptr, src.ptr); } | RCUPtr(RCUPtr &&src) : RCUPtr() { std::swap(ptr, src.ptr); } | ||||
RCUPtr &operator=(RCUPtr &&rhs) { | RCUPtr &operator=(RCUPtr &&rhs) { | ||||
std::swap(ptr, rhs.ptr); | std::swap(ptr, rhs.ptr); | ||||
return *this; | return *this; | ||||
} | } | ||||
/** | /** | ||||
* Accessors | * Get allows to access the undelying pointer. RCUPtr keeps ownership. | ||||
*/ | |||||
T *get() { return ptr; } | |||||
const T *get() const { return ptr; } | |||||
/** | |||||
* Release transfers ownership of the pointer from RCUPtr to the caller. | |||||
*/ | |||||
T *release() { | |||||
T *oldPtr = ptr; | |||||
ptr = nullptr; | |||||
return oldPtr; | |||||
} | |||||
/** | |||||
* Operator overloading for convenience. | |||||
*/ | */ | ||||
T *operator->() { return ptr; } | T *operator->() { return ptr; } | ||||
const T *operator->() const { return ptr; } | |||||
T &operator*() { return *ptr; } | |||||
const T &operator*() const { return *ptr; } | |||||
explicit operator bool() const { return ptr != nullptr; } | |||||
}; | }; | ||||
#define IMPLEMENT_RCU_REFCOUNT(T) \ | #define IMPLEMENT_RCU_REFCOUNT(T) \ | ||||
private: \ | private: \ | ||||
std::atomic<T> refcount{0}; \ | std::atomic<T> refcount{0}; \ | ||||
\ | \ | ||||
void acquire() { refcount++; } \ | void acquire() { refcount++; } \ | ||||
\ | \ | ||||
Show All 31 Lines |