-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathrcu_ptr.hpp
86 lines (68 loc) · 2.66 KB
/
rcu_ptr.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#pragma once
#include <detail/atomic_shared_ptr_traits.hpp>
#include <detail/atomic_shared_ptr.hpp>
#include <memory>
#include <atomic>
template <typename T, template <typename> class AtomicSharedPtr =
detail::__std::atomic_shared_ptr,
typename ASPTraits =
detail::atomic_shared_ptr_traits<AtomicSharedPtr> >
class rcu_ptr {
template <typename _T>
using atomic_shared_ptr =
typename ASPTraits::template atomic_shared_ptr<_T>;
atomic_shared_ptr<T> asp;
public:
template <typename _T>
using shared_ptr = typename ASPTraits::template shared_ptr<_T>;
using element_type = typename shared_ptr<T>::element_type;
// TODO add
// template <typename Y>
// rcu_ptr(const std::shared_ptr<Y>& r) {}
rcu_ptr() = default;
rcu_ptr(const shared_ptr<T>& desired) : asp(desired) {}
rcu_ptr(shared_ptr<T>&& desired) : asp(std::move(desired)) {}
rcu_ptr(const rcu_ptr&) = delete;
rcu_ptr& operator=(const rcu_ptr&) = delete;
rcu_ptr(rcu_ptr&&) = delete;
rcu_ptr& operator=(rcu_ptr&&) = delete;
~rcu_ptr() = default;
void operator=(const shared_ptr<T>& desired) { reset(desired); }
shared_ptr<const T> read() const {
return asp.load(std::memory_order_consume);
}
// Overwrites the content of the wrapped shared_ptr.
// We can use it to reset the wrapped data to a new value independent from
// the old value. ( e.g. vector.clear() )
void reset(const shared_ptr<T>& r) {
asp.store(r, std::memory_order_release);
}
void reset(shared_ptr<T>&& r) {
asp.store(std::move(r), std::memory_order_release);
}
// Updates the content of the wrapped shared_ptr.
// We can use it to update the wrapped data to a new value which is
// dependent from the old value ( e.g. vector.push_back() ).
//
// @param fun is a lambda which is called whenever an update
// needs to be done, i.e. it will be called continuously until the update is
// successful.
//
// A call expression with this function is invalid,
// if T is a non-copyable type.
template <typename R>
void copy_update(R&& fun) {
shared_ptr<T> sp_l = asp.load(std::memory_order_consume);
shared_ptr<T> r;
do {
if (sp_l) {
// deep copy
r = ASPTraits::template make_shared<T>(*sp_l);
}
// update
std::forward<R>(fun)(r.get());
} while (!asp.compare_exchange_strong(sp_l, std::move(r),
std::memory_order_release,
std::memory_order_consume));
}
};