22 std::atomic<RCUInfos *>
next;
27 std::map<uint64_t, std::function<void()>>
cleanups;
96 ptr->decrementRefCount();
112 template <
typename... Args>
static RCUPtr make(Args &&...args) {
113 return RCUPtr(
new T(std::forward<Args>(args)...));
120 if (
ptr !=
nullptr) {
121 ptr->incrementRefCount();
131 if (
ptr !=
nullptr) {
132 ptr->incrementRefCount();
147 if (
ptr !=
nullptr) {
148 ptr->incrementRefCount();
163 std::swap(
ptr, rhs.ptr);
191 explicit operator bool()
const {
return ptr !=
nullptr; }
197 return lhs.
get() == rhs;
201 return lhs == rhs.
get();
205 return !(lhs == rhs);
209 return !(lhs == rhs);
216 return stream << rhs.
ptr;
220#define IMPLEMENT_RCU_REFCOUNT(T) \
222 mutable std::atomic<T> refcount{0}; \
224 void incrementRefCount() const { \
228 bool tryDecrement() const { \
229 T count = refcount.load(); \
230 while (count > 0) { \
231 if (refcount.compare_exchange_weak(count, count - 1)) { \
239 void decrementRefCount() const { \
240 if (tryDecrement()) { \
244 RCULock::registerCleanup([this] { \
245 if (tryDecrement()) { \
253 static_assert(std::is_integral<T>::value, "T must be an integral type."); \
254 static_assert(std::is_unsigned<T>::value, "T must be unsigned."); \
256 template <typename> friend class ::RCUPtr
260template <
typename T>
struct hash<
RCUPtr<T>> {
262 return hash<
decltype(ptr.get())>()(ptr.get());
uint64_t hasSyncedTo(uint64_t cutoff=UNLOCKED)
std::atomic< RCUInfos * > next
static const uint64_t UNLOCKED
static thread_local RCUInfos infos
std::map< uint64_t, std::function< void()> > cleanups
std::atomic< uint64_t > state
static std::atomic< uint64_t > revision
void registerCleanup(const std::function< void()> &f)
static void registerCleanup(const std::function< void()> &f)
RCULock & operator=(const RCULock &)=delete
RCULock(RCUInfos *infosIn)
static void synchronize()
RCULock(const RCULock &)=delete
RCUPtr(RCUPtr &&src)
Move semantic.
RCUPtr & operator=(const RCUPtr &rhs)
friend bool operator!=(const RCUPtr &lhs, const RCUPtr &rhs)
const T * operator->() const
friend bool operator!=(const RCUPtr &lhs, const T *rhs)
friend bool operator==(const RCUPtr &lhs, const RCUPtr &rhs)
T * get()
Get allows to access the undelying pointer.
RCUPtr(const RCUPtr< U > &src)
Implicit converting constructor from RCUPtr to RCUPtr<T>, where U * is implicitely convertible to T *...
static RCUPtr acquire(T *&ptrIn)
Acquire ownership of some pointer.
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
T * release()
Release transfers ownership of the pointer from RCUPtr to the caller.
friend std::ostream & operator<<(std::ostream &stream, const RCUPtr &rhs)
ostream support.
RCUPtr & operator=(const RCUPtr< U > &rhs)
T * operator->()
Operator overloading for convenience.
static RCUPtr copy(T *ptr)
Construct a new RCUPtr without transferring owership.
RCUPtr(const RCUPtr &src)
Copy semantic.
friend bool operator==(const RCUPtr &lhs, const T *rhs)
Equality checks.
RCUPtr & operator=(RCUPtr &&rhs)
const T & operator*() const
Implement std::hash so RCUPtr can be used as a key for maps or sets.
size_t operator()(const RCUPtr< T > &ptr) const noexcept