19 #ifdef FOLLY_USE_LIBSTDCPP 26 #include <condition_variable> 34 using std::condition_variable;
38 using std::make_shared;
39 using std::memory_order;
40 using std::memory_order_acq_rel;
41 using std::memory_order_acquire;
42 using std::memory_order_relaxed;
43 using std::memory_order_release;
44 using std::memory_order_seq_cst;
48 using std::shared_ptr;
50 using std::unique_lock;
52 using std::chrono::duration_cast;
53 using std::chrono::microseconds;
54 using std::chrono::steady_clock;
61 static const char* memoryOrder(memory_order
order) {
63 case memory_order_relaxed:
65 case memory_order_acquire:
67 case memory_order_release:
69 case memory_order_acq_rel:
71 case memory_order_seq_cst:
79 void uncontended_read_write(
82 memory_order readOrder = memory_order_seq_cst,
83 memory_order writeOrder = memory_order_seq_cst) {
84 std::shared_ptr<int> zero = std::make_shared<int>(0);
87 for (
size_t i = 0;
i < 10000000; ++
i) {
88 for (
size_t j = 0; j < readers; ++j) {
91 for (
size_t j = 0; j < writers; ++j) {
92 a.store(zero, writeOrder);
96 cout <<
"Uncontended Read(" << readers <<
"," << memoryOrder(readOrder)
97 <<
")/Write(" << writers <<
"," << memoryOrder(writeOrder)
98 <<
"): " << (time2 - time1) <<
" \u03BCs" << endl;
101 template <
typename T>
103 unique_lock<mutex>
lock,
104 condition_variable& cvar,
107 memory_order order) {
108 cvar.wait(lock, [&go]() {
109 return atomic_load_explicit(&go, memory_order_acquire);
112 for (
size_t i = 0;
i < 1000000; ++
i) {
117 template <
typename T>
119 unique_lock<mutex> lock,
120 condition_variable& cvar,
123 memory_order order) {
124 std::shared_ptr<int> zero = std::make_shared<int>(0);
125 cvar.wait(lock, [&go]() {
126 return atomic_load_explicit(&go, memory_order_acquire);
129 for (
size_t i = 0;
i < 1000000; ++
i) {
130 aptr.store(zero, order);
134 template <
typename T>
135 void contended_read_write(
138 memory_order readOrder = memory_order_seq_cst,
139 memory_order writeOrder = memory_order_seq_cst) {
142 condition_variable cvar;
143 atomic<bool> go{
false};
144 T aptr(std::make_shared<int>());
145 for (
size_t i = 0;
i < readers; ++
i) {
146 unique_lock<mutex>
ulock(lock);
147 threads.emplace_back(
148 &read_asp<T>,
move(
ulock), ref(cvar), ref(go), ref(aptr), readOrder);
150 for (
size_t i = 0;
i < writers; ++
i) {
151 unique_lock<mutex>
ulock(lock);
152 threads.emplace_back(
153 &write_asp<T>,
move(
ulock), ref(cvar), ref(go), ref(aptr), writeOrder);
155 unique_lock<mutex>
ulock(lock);
157 atomic_store_explicit(&go,
true, memory_order_release);
160 for (
auto& thread : threads) {
164 cout <<
"Contended Read(" << readers <<
"," << memoryOrder(readOrder)
165 <<
")/Write(" << writers <<
"," << memoryOrder(writeOrder)
166 <<
"): " << (time2 - time1) <<
" \u03BCs" << endl;
169 template <
typename T>
170 void document_noexcept() {
173 cout <<
" ctor () is " << (
noexcept(
T()) ?
"" :
"not ") <<
"noexcept." 175 cout <<
" ctor (ptr) is " << (
noexcept(
T(ptr)) ?
"" :
"not ") <<
"noexcept." 179 cout << " " #A " is " << (noexcept(aptr.A) ? "" : "not ") << "noexcept." \ 187 _(store(ptr, memory_order_seq_cst));
190 _(
load(memory_order_seq_cst));
195 _(compare_exchange_strong(ptr, ptr));
196 _(compare_exchange_strong(ptr, ptr, memory_order_seq_cst));
197 _(compare_exchange_strong(
198 ptr, ptr, memory_order_seq_cst, memory_order_seq_cst));
200 _(compare_exchange_weak(ptr, ptr));
201 _(compare_exchange_weak(ptr, ptr, memory_order_seq_cst));
202 _(compare_exchange_weak(
203 ptr, ptr, memory_order_seq_cst, memory_order_seq_cst));
206 cout <<
" operator std::shared_ptr<T>() is " 207 << (
noexcept(ptr = aptr) ?
"" :
"not ") <<
"noexcept." << endl;
210 template <
typename T>
212 document_noexcept<T>();
213 uncontended_read_write<T>(10, 0);
214 uncontended_read_write<T>(0, 10);
215 uncontended_read_write<T>(10, 10);
216 uncontended_read_write<T>(10, 10, memory_order_relaxed, memory_order_relaxed);
217 uncontended_read_write<T>(10, 10, memory_order_acquire, memory_order_release);
218 contended_read_write<T>(10, 0);
219 contended_read_write<T>(0, 10);
220 contended_read_write<T>(1, 1);
221 contended_read_write<T>(5, 1);
222 contended_read_write<T>(10, 1);
223 contended_read_write<T>(100, 1);
224 contended_read_write<T>(100, 1, memory_order_relaxed, memory_order_relaxed);
225 contended_read_write<T>(100, 1, memory_order_acquire, memory_order_release);
228 int main(
int,
char**) {
229 cout << endl <<
"Folly implementation. Is lock free: 1" << endl;
230 runSuite<folly::atomic_shared_ptr<int>>();
234 #else // #ifdef FOLLY_USE_LIBSTDCPP 240 #endif // #ifdef FOLLY_USE_LIBSTDCPP
std::chrono::steady_clock::time_point now()
constexpr detail::Map< Move > move
requires E e noexcept(noexcept(s.error(std::move(e))))
std::vector< std::thread::id > threads
auto lock(SynchronizedLocker...lockersIn) -> std::tuple< typename SynchronizedLocker::LockedPtr... >
auto ulock(Synchronized &synchronized, Args &&...args)
T exchange(T &obj, U &&new_value)
const internal::AnythingMatcher _