8 #include <boost/noncopyable.hpp> 16 #include <type_traits> 24 std::atomic<RCUInfos *>
next;
26 std::map<uint64_t, std::function<void()>>
cleanups;
41 state.store(UNLOCKED);
60 class RCULock :
public boost::noncopyable {
82 explicit RCUPtr(T *ptrIn) : ptr(ptrIn) {}
105 template <
typename... Args>
static RCUPtr make(Args &&... args) {
106 return RCUPtr(
new T(std::forward<Args>(args)...));
113 if (ptr !=
nullptr) {
124 if (ptr !=
nullptr) {
131 std::swap(ptr, tmp.
ptr);
140 std::swap(ptr, rhs.ptr);
147 T *
get() {
return ptr; }
148 const T *
get()
const {
return ptr; }
168 explicit operator bool()
const {
return ptr !=
nullptr; }
174 return lhs.
get() == rhs;
178 return lhs == rhs.
get();
182 return !(lhs == rhs);
186 return !(lhs == rhs);
193 return stream << rhs.
ptr;
197 #define IMPLEMENT_RCU_REFCOUNT(T) \ 199 mutable std::atomic<T> refcount{0}; \ 201 void acquire() const { refcount++; } \ 203 bool tryDecrement() const { \ 204 T count = refcount.load(); \ 205 while (count > 0) { \ 206 if (refcount.compare_exchange_weak(count, count - 1)) { \ 214 void release() const { \ 215 if (tryDecrement()) { \ 219 RCULock::registerCleanup([this] { \ 220 if (tryDecrement()) { \ 228 static_assert(std::is_integral<T>::value, "T must be an integral type."); \ 229 static_assert(std::is_unsigned<T>::value, "T must be unsigned."); \ 231 template <typename> friend class ::RCUPtr 233 #endif // BITCOIN_RCU_H
const T * operator->() const
RCUPtr(RCUPtr &&src)
Move semantic.
static RCUPtr acquire(T *&ptrIn)
Acquire ownership of some pointer.
friend bool operator==(const RCUPtr &lhs, const T *rhs)
Equality checks.
RCULock(RCUInfos *infosIn)
static thread_local RCUInfos infos
friend bool operator!=(const RCUPtr &lhs, const T *rhs)
T * get()
Get allows to access the undelying pointer.
uint64_t hasSyncedTo(uint64_t cutoff=UNLOCKED)
std::map< uint64_t, std::function< void()> > cleanups
T * operator->()
Operator overloading for convenience.
static std::atomic< uint64_t > revision
static RCUPtr make(Args &&... args)
Construct a new object that is owned by the pointer.
RCUPtr & operator=(RCUPtr &&rhs)
RCUPtr & operator=(const RCUPtr &rhs)
friend std::ostream & operator<<(std::ostream &stream, const RCUPtr &rhs)
ostream support.
friend bool operator!=(const RCUPtr &lhs, const RCUPtr &rhs)
friend bool operator==(const RCUPtr &lhs, const RCUPtr &rhs)
const T & operator*() const
static void registerCleanup(const std::function< void()> &f)
static void synchronize()
T * release()
Release transfers ownership of the pointer from RCUPtr to the caller.
RCUPtr(const RCUPtr &src)
Copy semantic.
static RCUPtr copy(T *ptr)
Construct a new RCUPtr without transferring owership.
void registerCleanup(const std::function< void()> &f)
std::atomic< RCUInfos * > next
static const uint64_t UNLOCKED
std::atomic< uint64_t > state