atomic 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef _LIBCPP_ATOMIC
  10. #define _LIBCPP_ATOMIC
  11. /*
  12. atomic synopsis
  13. namespace std
  14. {
  15. // feature test macro [version.syn]
  16. #define __cpp_lib_atomic_is_always_lock_free
  17. #define __cpp_lib_atomic_flag_test
  18. #define __cpp_lib_atomic_lock_free_type_aliases
  19. #define __cpp_lib_atomic_wait
  20. // order and consistency
  21. enum memory_order: unspecified // enum class in C++20
  22. {
  23. relaxed,
  24. consume, // load-consume
  25. acquire, // load-acquire
  26. release, // store-release
  27. acq_rel, // store-release load-acquire
  28. seq_cst // store-release load-acquire
  29. };
  30. inline constexpr auto memory_order_relaxed = memory_order::relaxed;
  31. inline constexpr auto memory_order_consume = memory_order::consume;
  32. inline constexpr auto memory_order_acquire = memory_order::acquire;
  33. inline constexpr auto memory_order_release = memory_order::release;
  34. inline constexpr auto memory_order_acq_rel = memory_order::acq_rel;
  35. inline constexpr auto memory_order_seq_cst = memory_order::seq_cst;
  36. template <class T> T kill_dependency(T y) noexcept;
  37. // lock-free property
  38. #define ATOMIC_BOOL_LOCK_FREE unspecified
  39. #define ATOMIC_CHAR_LOCK_FREE unspecified
  40. #define ATOMIC_CHAR8_T_LOCK_FREE unspecified // C++20
  41. #define ATOMIC_CHAR16_T_LOCK_FREE unspecified
  42. #define ATOMIC_CHAR32_T_LOCK_FREE unspecified
  43. #define ATOMIC_WCHAR_T_LOCK_FREE unspecified
  44. #define ATOMIC_SHORT_LOCK_FREE unspecified
  45. #define ATOMIC_INT_LOCK_FREE unspecified
  46. #define ATOMIC_LONG_LOCK_FREE unspecified
  47. #define ATOMIC_LLONG_LOCK_FREE unspecified
  48. #define ATOMIC_POINTER_LOCK_FREE unspecified
  49. template <class T>
  50. struct atomic
  51. {
  52. using value_type = T;
  53. static constexpr bool is_always_lock_free;
  54. bool is_lock_free() const volatile noexcept;
  55. bool is_lock_free() const noexcept;
  56. atomic() noexcept = default; // until C++20
  57. constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>); // since C++20
  58. constexpr atomic(T desr) noexcept;
  59. atomic(const atomic&) = delete;
  60. atomic& operator=(const atomic&) = delete;
  61. atomic& operator=(const atomic&) volatile = delete;
  62. T load(memory_order m = memory_order_seq_cst) const volatile noexcept;
  63. T load(memory_order m = memory_order_seq_cst) const noexcept;
  64. operator T() const volatile noexcept;
  65. operator T() const noexcept;
  66. void store(T desr, memory_order m = memory_order_seq_cst) volatile noexcept;
  67. void store(T desr, memory_order m = memory_order_seq_cst) noexcept;
  68. T operator=(T) volatile noexcept;
  69. T operator=(T) noexcept;
  70. T exchange(T desr, memory_order m = memory_order_seq_cst) volatile noexcept;
  71. T exchange(T desr, memory_order m = memory_order_seq_cst) noexcept;
  72. bool compare_exchange_weak(T& expc, T desr,
  73. memory_order s, memory_order f) volatile noexcept;
  74. bool compare_exchange_weak(T& expc, T desr, memory_order s, memory_order f) noexcept;
  75. bool compare_exchange_strong(T& expc, T desr,
  76. memory_order s, memory_order f) volatile noexcept;
  77. bool compare_exchange_strong(T& expc, T desr,
  78. memory_order s, memory_order f) noexcept;
  79. bool compare_exchange_weak(T& expc, T desr,
  80. memory_order m = memory_order_seq_cst) volatile noexcept;
  81. bool compare_exchange_weak(T& expc, T desr,
  82. memory_order m = memory_order_seq_cst) noexcept;
  83. bool compare_exchange_strong(T& expc, T desr,
  84. memory_order m = memory_order_seq_cst) volatile noexcept;
  85. bool compare_exchange_strong(T& expc, T desr,
  86. memory_order m = memory_order_seq_cst) noexcept;
  87. void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept;
  88. void wait(T, memory_order = memory_order::seq_cst) const noexcept;
  89. void notify_one() volatile noexcept;
  90. void notify_one() noexcept;
  91. void notify_all() volatile noexcept;
  92. void notify_all() noexcept;
  93. };
  94. template <>
  95. struct atomic<integral>
  96. {
  97. using value_type = integral;
  98. using difference_type = value_type;
  99. static constexpr bool is_always_lock_free;
  100. bool is_lock_free() const volatile noexcept;
  101. bool is_lock_free() const noexcept;
  102. atomic() noexcept = default;
  103. constexpr atomic(integral desr) noexcept;
  104. atomic(const atomic&) = delete;
  105. atomic& operator=(const atomic&) = delete;
  106. atomic& operator=(const atomic&) volatile = delete;
  107. integral load(memory_order m = memory_order_seq_cst) const volatile noexcept;
  108. integral load(memory_order m = memory_order_seq_cst) const noexcept;
  109. operator integral() const volatile noexcept;
  110. operator integral() const noexcept;
  111. void store(integral desr, memory_order m = memory_order_seq_cst) volatile noexcept;
  112. void store(integral desr, memory_order m = memory_order_seq_cst) noexcept;
  113. integral operator=(integral desr) volatile noexcept;
  114. integral operator=(integral desr) noexcept;
  115. integral exchange(integral desr,
  116. memory_order m = memory_order_seq_cst) volatile noexcept;
  117. integral exchange(integral desr, memory_order m = memory_order_seq_cst) noexcept;
  118. bool compare_exchange_weak(integral& expc, integral desr,
  119. memory_order s, memory_order f) volatile noexcept;
  120. bool compare_exchange_weak(integral& expc, integral desr,
  121. memory_order s, memory_order f) noexcept;
  122. bool compare_exchange_strong(integral& expc, integral desr,
  123. memory_order s, memory_order f) volatile noexcept;
  124. bool compare_exchange_strong(integral& expc, integral desr,
  125. memory_order s, memory_order f) noexcept;
  126. bool compare_exchange_weak(integral& expc, integral desr,
  127. memory_order m = memory_order_seq_cst) volatile noexcept;
  128. bool compare_exchange_weak(integral& expc, integral desr,
  129. memory_order m = memory_order_seq_cst) noexcept;
  130. bool compare_exchange_strong(integral& expc, integral desr,
  131. memory_order m = memory_order_seq_cst) volatile noexcept;
  132. bool compare_exchange_strong(integral& expc, integral desr,
  133. memory_order m = memory_order_seq_cst) noexcept;
  134. integral fetch_add(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
  135. integral fetch_add(integral op, memory_order m = memory_order_seq_cst) noexcept;
  136. integral fetch_sub(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
  137. integral fetch_sub(integral op, memory_order m = memory_order_seq_cst) noexcept;
  138. integral fetch_and(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
  139. integral fetch_and(integral op, memory_order m = memory_order_seq_cst) noexcept;
  140. integral fetch_or(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
  141. integral fetch_or(integral op, memory_order m = memory_order_seq_cst) noexcept;
  142. integral fetch_xor(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
  143. integral fetch_xor(integral op, memory_order m = memory_order_seq_cst) noexcept;
  144. integral operator++(int) volatile noexcept;
  145. integral operator++(int) noexcept;
  146. integral operator--(int) volatile noexcept;
  147. integral operator--(int) noexcept;
  148. integral operator++() volatile noexcept;
  149. integral operator++() noexcept;
  150. integral operator--() volatile noexcept;
  151. integral operator--() noexcept;
  152. integral operator+=(integral op) volatile noexcept;
  153. integral operator+=(integral op) noexcept;
  154. integral operator-=(integral op) volatile noexcept;
  155. integral operator-=(integral op) noexcept;
  156. integral operator&=(integral op) volatile noexcept;
  157. integral operator&=(integral op) noexcept;
  158. integral operator|=(integral op) volatile noexcept;
  159. integral operator|=(integral op) noexcept;
  160. integral operator^=(integral op) volatile noexcept;
  161. integral operator^=(integral op) noexcept;
  162. void wait(integral, memory_order = memory_order::seq_cst) const volatile noexcept;
  163. void wait(integral, memory_order = memory_order::seq_cst) const noexcept;
  164. void notify_one() volatile noexcept;
  165. void notify_one() noexcept;
  166. void notify_all() volatile noexcept;
  167. void notify_all() noexcept;
  168. };
  169. template <class T>
  170. struct atomic<T*>
  171. {
  172. using value_type = T*;
  173. using difference_type = ptrdiff_t;
  174. static constexpr bool is_always_lock_free;
  175. bool is_lock_free() const volatile noexcept;
  176. bool is_lock_free() const noexcept;
  177. atomic() noexcept = default; // until C++20
  178. constexpr atomic() noexcept; // since C++20
  179. constexpr atomic(T* desr) noexcept;
  180. atomic(const atomic&) = delete;
  181. atomic& operator=(const atomic&) = delete;
  182. atomic& operator=(const atomic&) volatile = delete;
  183. T* load(memory_order m = memory_order_seq_cst) const volatile noexcept;
  184. T* load(memory_order m = memory_order_seq_cst) const noexcept;
  185. operator T*() const volatile noexcept;
  186. operator T*() const noexcept;
  187. void store(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept;
  188. void store(T* desr, memory_order m = memory_order_seq_cst) noexcept;
  189. T* operator=(T*) volatile noexcept;
  190. T* operator=(T*) noexcept;
  191. T* exchange(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept;
  192. T* exchange(T* desr, memory_order m = memory_order_seq_cst) noexcept;
  193. bool compare_exchange_weak(T*& expc, T* desr,
  194. memory_order s, memory_order f) volatile noexcept;
  195. bool compare_exchange_weak(T*& expc, T* desr,
  196. memory_order s, memory_order f) noexcept;
  197. bool compare_exchange_strong(T*& expc, T* desr,
  198. memory_order s, memory_order f) volatile noexcept;
  199. bool compare_exchange_strong(T*& expc, T* desr,
  200. memory_order s, memory_order f) noexcept;
  201. bool compare_exchange_weak(T*& expc, T* desr,
  202. memory_order m = memory_order_seq_cst) volatile noexcept;
  203. bool compare_exchange_weak(T*& expc, T* desr,
  204. memory_order m = memory_order_seq_cst) noexcept;
  205. bool compare_exchange_strong(T*& expc, T* desr,
  206. memory_order m = memory_order_seq_cst) volatile noexcept;
  207. bool compare_exchange_strong(T*& expc, T* desr,
  208. memory_order m = memory_order_seq_cst) noexcept;
  209. T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept;
  210. T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) noexcept;
  211. T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept;
  212. T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) noexcept;
  213. T* operator++(int) volatile noexcept;
  214. T* operator++(int) noexcept;
  215. T* operator--(int) volatile noexcept;
  216. T* operator--(int) noexcept;
  217. T* operator++() volatile noexcept;
  218. T* operator++() noexcept;
  219. T* operator--() volatile noexcept;
  220. T* operator--() noexcept;
  221. T* operator+=(ptrdiff_t op) volatile noexcept;
  222. T* operator+=(ptrdiff_t op) noexcept;
  223. T* operator-=(ptrdiff_t op) volatile noexcept;
  224. T* operator-=(ptrdiff_t op) noexcept;
  225. void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept;
  226. void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
  227. void notify_one() volatile noexcept;
  228. void notify_one() noexcept;
  229. void notify_all() volatile noexcept;
  230. void notify_all() noexcept;
  231. };
  232. template<>
  233. struct atomic<floating-point-type> { // since C++20
  234. using value_type = floating-point-type;
  235. using difference_type = value_type;
  236. static constexpr bool is_always_lock_free = implementation-defined;
  237. bool is_lock_free() const volatile noexcept;
  238. bool is_lock_free() const noexcept;
  239. constexpr atomic() noexcept;
  240. constexpr atomic(floating-point-type) noexcept;
  241. atomic(const atomic&) = delete;
  242. atomic& operator=(const atomic&) = delete;
  243. atomic& operator=(const atomic&) volatile = delete;
  244. void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
  245. void store(floating-point-type, memory_order = memory_order::seq_cst) noexcept;
  246. floating-point-type operator=(floating-point-type) volatile noexcept;
  247. floating-point-type operator=(floating-point-type) noexcept;
  248. floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept;
  249. floating-point-type load(memory_order = memory_order::seq_cst) noexcept;
  250. operator floating-point-type() volatile noexcept;
  251. operator floating-point-type() noexcept;
  252. floating-point-type exchange(floating-point-type,
  253. memory_order = memory_order::seq_cst) volatile noexcept;
  254. floating-point-type exchange(floating-point-type,
  255. memory_order = memory_order::seq_cst) noexcept;
  256. bool compare_exchange_weak(floating-point-type&, floating-point-type,
  257. memory_order, memory_order) volatile noexcept;
  258. bool compare_exchange_weak(floating-point-type&, floating-point-type,
  259. memory_order, memory_order) noexcept;
  260. bool compare_exchange_strong(floating-point-type&, floating-point-type,
  261. memory_order, memory_order) volatile noexcept;
  262. bool compare_exchange_strong(floating-point-type&, floating-point-type,
  263. memory_order, memory_order) noexcept;
  264. bool compare_exchange_weak(floating-point-type&, floating-point-type,
  265. memory_order = memory_order::seq_cst) volatile noexcept;
  266. bool compare_exchange_weak(floating-point-type&, floating-point-type,
  267. memory_order = memory_order::seq_cst) noexcept;
  268. bool compare_exchange_strong(floating-point-type&, floating-point-type,
  269. memory_order = memory_order::seq_cst) volatile noexcept;
  270. bool compare_exchange_strong(floating-point-type&, floating-point-type,
  271. memory_order = memory_order::seq_cst) noexcept;
  272. floating-point-type fetch_add(floating-point-type,
  273. memory_order = memory_order::seq_cst) volatile noexcept;
  274. floating-point-type fetch_add(floating-point-type,
  275. memory_order = memory_order::seq_cst) noexcept;
  276. floating-point-type fetch_sub(floating-point-type,
  277. memory_order = memory_order::seq_cst) volatile noexcept;
  278. floating-point-type fetch_sub(floating-point-type,
  279. memory_order = memory_order::seq_cst) noexcept;
  280. floating-point-type operator+=(floating-point-type) volatile noexcept;
  281. floating-point-type operator+=(floating-point-type) noexcept;
  282. floating-point-type operator-=(floating-point-type) volatile noexcept;
  283. floating-point-type operator-=(floating-point-type) noexcept;
  284. void wait(floating-point-type, memory_order = memory_order::seq_cst) const volatile noexcept;
  285. void wait(floating-point-type, memory_order = memory_order::seq_cst) const noexcept;
  286. void notify_one() volatile noexcept;
  287. void notify_one() noexcept;
  288. void notify_all() volatile noexcept;
  289. void notify_all() noexcept;
  290. };
  291. // [atomics.nonmembers], non-member functions
  292. template<class T>
  293. bool atomic_is_lock_free(const volatile atomic<T>*) noexcept;
  294. template<class T>
  295. bool atomic_is_lock_free(const atomic<T>*) noexcept;
  296. template<class T>
  297. void atomic_store(volatile atomic<T>*, atomic<T>::value_type) noexcept;
  298. template<class T>
  299. void atomic_store(atomic<T>*, atomic<T>::value_type) noexcept;
  300. template<class T>
  301. void atomic_store_explicit(volatile atomic<T>*, atomic<T>::value_type,
  302. memory_order) noexcept;
  303. template<class T>
  304. void atomic_store_explicit(atomic<T>*, atomic<T>::value_type,
  305. memory_order) noexcept;
  306. template<class T>
  307. T atomic_load(const volatile atomic<T>*) noexcept;
  308. template<class T>
  309. T atomic_load(const atomic<T>*) noexcept;
  310. template<class T>
  311. T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept;
  312. template<class T>
  313. T atomic_load_explicit(const atomic<T>*, memory_order) noexcept;
  314. template<class T>
  315. T atomic_exchange(volatile atomic<T>*, atomic<T>::value_type) noexcept;
  316. template<class T>
  317. T atomic_exchange(atomic<T>*, atomic<T>::value_type) noexcept;
  318. template<class T>
  319. T atomic_exchange_explicit(volatile atomic<T>*, atomic<T>::value_type,
  320. memory_order) noexcept;
  321. template<class T>
  322. T atomic_exchange_explicit(atomic<T>*, atomic<T>::value_type,
  323. memory_order) noexcept;
  324. template<class T>
  325. bool atomic_compare_exchange_weak(volatile atomic<T>*, atomic<T>::value_type*,
  326. atomic<T>::value_type) noexcept;
  327. template<class T>
  328. bool atomic_compare_exchange_weak(atomic<T>*, atomic<T>::value_type*,
  329. atomic<T>::value_type) noexcept;
  330. template<class T>
  331. bool atomic_compare_exchange_strong(volatile atomic<T>*, atomic<T>::value_type*,
  332. atomic<T>::value_type) noexcept;
  333. template<class T>
  334. bool atomic_compare_exchange_strong(atomic<T>*, atomic<T>::value_type*,
  335. atomic<T>::value_type) noexcept;
  336. template<class T>
  337. bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*, atomic<T>::value_type*,
  338. atomic<T>::value_type,
  339. memory_order, memory_order) noexcept;
  340. template<class T>
  341. bool atomic_compare_exchange_weak_explicit(atomic<T>*, atomic<T>::value_type*,
  342. atomic<T>::value_type,
  343. memory_order, memory_order) noexcept;
  344. template<class T>
  345. bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*, atomic<T>::value_type*,
  346. atomic<T>::value_type,
  347. memory_order, memory_order) noexcept;
  348. template<class T>
  349. bool atomic_compare_exchange_strong_explicit(atomic<T>*, atomic<T>::value_type*,
  350. atomic<T>::value_type,
  351. memory_order, memory_order) noexcept;
  352. template<class T>
  353. T atomic_fetch_add(volatile atomic<T>*, atomic<T>::difference_type) noexcept;
  354. template<class T>
  355. T atomic_fetch_add(atomic<T>*, atomic<T>::difference_type) noexcept;
  356. template<class T>
  357. T atomic_fetch_add_explicit(volatile atomic<T>*, atomic<T>::difference_type,
  358. memory_order) noexcept;
  359. template<class T>
  360. T atomic_fetch_add_explicit(atomic<T>*, atomic<T>::difference_type,
  361. memory_order) noexcept;
  362. template<class T>
  363. T atomic_fetch_sub(volatile atomic<T>*, atomic<T>::difference_type) noexcept;
  364. template<class T>
  365. T atomic_fetch_sub(atomic<T>*, atomic<T>::difference_type) noexcept;
  366. template<class T>
  367. T atomic_fetch_sub_explicit(volatile atomic<T>*, atomic<T>::difference_type,
  368. memory_order) noexcept;
  369. template<class T>
  370. T atomic_fetch_sub_explicit(atomic<T>*, atomic<T>::difference_type,
  371. memory_order) noexcept;
  372. template<class T>
  373. T atomic_fetch_and(volatile atomic<T>*, atomic<T>::value_type) noexcept;
  374. template<class T>
  375. T atomic_fetch_and(atomic<T>*, atomic<T>::value_type) noexcept;
  376. template<class T>
  377. T atomic_fetch_and_explicit(volatile atomic<T>*, atomic<T>::value_type,
  378. memory_order) noexcept;
  379. template<class T>
  380. T atomic_fetch_and_explicit(atomic<T>*, atomic<T>::value_type,
  381. memory_order) noexcept;
  382. template<class T>
  383. T atomic_fetch_or(volatile atomic<T>*, atomic<T>::value_type) noexcept;
  384. template<class T>
  385. T atomic_fetch_or(atomic<T>*, atomic<T>::value_type) noexcept;
  386. template<class T>
  387. T atomic_fetch_or_explicit(volatile atomic<T>*, atomic<T>::value_type,
  388. memory_order) noexcept;
  389. template<class T>
  390. T atomic_fetch_or_explicit(atomic<T>*, atomic<T>::value_type,
  391. memory_order) noexcept;
  392. template<class T>
  393. T atomic_fetch_xor(volatile atomic<T>*, atomic<T>::value_type) noexcept;
  394. template<class T>
  395. T atomic_fetch_xor(atomic<T>*, atomic<T>::value_type) noexcept;
  396. template<class T>
  397. T atomic_fetch_xor_explicit(volatile atomic<T>*, atomic<T>::value_type,
  398. memory_order) noexcept;
  399. template<class T>
  400. T atomic_fetch_xor_explicit(atomic<T>*, atomic<T>::value_type,
  401. memory_order) noexcept;
  402. template<class T>
  403. void atomic_wait(const volatile atomic<T>*, atomic<T>::value_type) noexcept;
  404. template<class T>
  405. void atomic_wait(const atomic<T>*, atomic<T>::value_type) noexcept;
  406. template<class T>
  407. void atomic_wait_explicit(const volatile atomic<T>*, atomic<T>::value_type,
  408. memory_order) noexcept;
  409. template<class T>
  410. void atomic_wait_explicit(const atomic<T>*, atomic<T>::value_type,
  411. memory_order) noexcept;
  412. template<class T>
  413. void atomic_notify_one(volatile atomic<T>*) noexcept;
  414. template<class T>
  415. void atomic_notify_one(atomic<T>*) noexcept;
  416. template<class T>
  417. void atomic_notify_all(volatile atomic<T>*) noexcept;
  418. template<class T>
  419. void atomic_notify_all(atomic<T>*) noexcept;
  420. // Atomics for standard typedef types
  421. typedef atomic<bool> atomic_bool;
  422. typedef atomic<char> atomic_char;
  423. typedef atomic<signed char> atomic_schar;
  424. typedef atomic<unsigned char> atomic_uchar;
  425. typedef atomic<short> atomic_short;
  426. typedef atomic<unsigned short> atomic_ushort;
  427. typedef atomic<int> atomic_int;
  428. typedef atomic<unsigned int> atomic_uint;
  429. typedef atomic<long> atomic_long;
  430. typedef atomic<unsigned long> atomic_ulong;
  431. typedef atomic<long long> atomic_llong;
  432. typedef atomic<unsigned long long> atomic_ullong;
  433. typedef atomic<char8_t> atomic_char8_t; // C++20
  434. typedef atomic<char16_t> atomic_char16_t;
  435. typedef atomic<char32_t> atomic_char32_t;
  436. typedef atomic<wchar_t> atomic_wchar_t;
  437. typedef atomic<int_least8_t> atomic_int_least8_t;
  438. typedef atomic<uint_least8_t> atomic_uint_least8_t;
  439. typedef atomic<int_least16_t> atomic_int_least16_t;
  440. typedef atomic<uint_least16_t> atomic_uint_least16_t;
  441. typedef atomic<int_least32_t> atomic_int_least32_t;
  442. typedef atomic<uint_least32_t> atomic_uint_least32_t;
  443. typedef atomic<int_least64_t> atomic_int_least64_t;
  444. typedef atomic<uint_least64_t> atomic_uint_least64_t;
  445. typedef atomic<int_fast8_t> atomic_int_fast8_t;
  446. typedef atomic<uint_fast8_t> atomic_uint_fast8_t;
  447. typedef atomic<int_fast16_t> atomic_int_fast16_t;
  448. typedef atomic<uint_fast16_t> atomic_uint_fast16_t;
  449. typedef atomic<int_fast32_t> atomic_int_fast32_t;
  450. typedef atomic<uint_fast32_t> atomic_uint_fast32_t;
  451. typedef atomic<int_fast64_t> atomic_int_fast64_t;
  452. typedef atomic<uint_fast64_t> atomic_uint_fast64_t;
  453. typedef atomic<int8_t> atomic_int8_t;
  454. typedef atomic<uint8_t> atomic_uint8_t;
  455. typedef atomic<int16_t> atomic_int16_t;
  456. typedef atomic<uint16_t> atomic_uint16_t;
  457. typedef atomic<int32_t> atomic_int32_t;
  458. typedef atomic<uint32_t> atomic_uint32_t;
  459. typedef atomic<int64_t> atomic_int64_t;
  460. typedef atomic<uint64_t> atomic_uint64_t;
  461. typedef atomic<intptr_t> atomic_intptr_t;
  462. typedef atomic<uintptr_t> atomic_uintptr_t;
  463. typedef atomic<size_t> atomic_size_t;
  464. typedef atomic<ptrdiff_t> atomic_ptrdiff_t;
  465. typedef atomic<intmax_t> atomic_intmax_t;
  466. typedef atomic<uintmax_t> atomic_uintmax_t;
  467. typedef see-below atomic_signed_lock_free; // since C++20
  468. typedef see-below atomic_unsigned_lock_free; // since C++20
  469. // flag type and operations
  470. typedef struct atomic_flag
  471. {
  472. atomic_flag() noexcept = default; // until C++20
  473. constexpr atomic_flag() noexcept; // since C++20
  474. atomic_flag(const atomic_flag&) = delete;
  475. atomic_flag& operator=(const atomic_flag&) = delete;
  476. atomic_flag& operator=(const atomic_flag&) volatile = delete;
  477. bool test(memory_order m = memory_order_seq_cst) volatile noexcept;
  478. bool test(memory_order m = memory_order_seq_cst) noexcept;
  479. bool test_and_set(memory_order m = memory_order_seq_cst) volatile noexcept;
  480. bool test_and_set(memory_order m = memory_order_seq_cst) noexcept;
  481. void clear(memory_order m = memory_order_seq_cst) volatile noexcept;
  482. void clear(memory_order m = memory_order_seq_cst) noexcept;
  483. void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept;
  484. void wait(bool, memory_order = memory_order::seq_cst) const noexcept;
  485. void notify_one() volatile noexcept;
  486. void notify_one() noexcept;
  487. void notify_all() volatile noexcept;
  488. void notify_all() noexcept;
  489. } atomic_flag;
  490. bool atomic_flag_test(volatile atomic_flag* obj) noexcept;
  491. bool atomic_flag_test(atomic_flag* obj) noexcept;
  492. bool atomic_flag_test_explicit(volatile atomic_flag* obj,
  493. memory_order m) noexcept;
  494. bool atomic_flag_test_explicit(atomic_flag* obj, memory_order m) noexcept;
  495. bool atomic_flag_test_and_set(volatile atomic_flag* obj) noexcept;
  496. bool atomic_flag_test_and_set(atomic_flag* obj) noexcept;
  497. bool atomic_flag_test_and_set_explicit(volatile atomic_flag* obj,
  498. memory_order m) noexcept;
  499. bool atomic_flag_test_and_set_explicit(atomic_flag* obj, memory_order m) noexcept;
  500. void atomic_flag_clear(volatile atomic_flag* obj) noexcept;
  501. void atomic_flag_clear(atomic_flag* obj) noexcept;
  502. void atomic_flag_clear_explicit(volatile atomic_flag* obj, memory_order m) noexcept;
  503. void atomic_flag_clear_explicit(atomic_flag* obj, memory_order m) noexcept;
  504. void atomic_wait(const volatile atomic_flag* obj, T old) noexcept;
  505. void atomic_wait(const atomic_flag* obj, T old) noexcept;
  506. void atomic_wait_explicit(const volatile atomic_flag* obj, T old, memory_order m) noexcept;
  507. void atomic_wait_explicit(const atomic_flag* obj, T old, memory_order m) noexcept;
  508. void atomic_one(volatile atomic_flag* obj) noexcept;
  509. void atomic_one(atomic_flag* obj) noexcept;
  510. void atomic_all(volatile atomic_flag* obj) noexcept;
  511. void atomic_all(atomic_flag* obj) noexcept;
  512. // fences
  513. void atomic_thread_fence(memory_order m) noexcept;
  514. void atomic_signal_fence(memory_order m) noexcept;
  515. // deprecated
  516. template <class T>
  517. void atomic_init(volatile atomic<T>* obj, atomic<T>::value_type desr) noexcept;
  518. template <class T>
  519. void atomic_init(atomic<T>* obj, atomic<T>::value_type desr) noexcept;
  520. #define ATOMIC_VAR_INIT(value) see below
  521. #define ATOMIC_FLAG_INIT see below
  522. } // std
  523. */
  524. #include <__config>
  525. #if _LIBCPP_STD_VER < 23 && defined(_LIBCPP_STDATOMIC_H)
  526. # error <atomic> is incompatible with <stdatomic.h> before C++23. Please compile with -std=c++23.
  527. #endif
  528. #include <__atomic/aliases.h>
  529. #include <__atomic/atomic.h>
  530. #include <__atomic/atomic_base.h>
  531. #include <__atomic/atomic_flag.h>
  532. #include <__atomic/atomic_init.h>
  533. #include <__atomic/atomic_lock_free.h>
  534. #include <__atomic/atomic_sync.h>
  535. #include <__atomic/check_memory_order.h>
  536. #include <__atomic/contention_t.h>
  537. #include <__atomic/cxx_atomic_impl.h>
  538. #include <__atomic/fence.h>
  539. #include <__atomic/is_always_lock_free.h>
  540. #include <__atomic/kill_dependency.h>
  541. #include <__atomic/memory_order.h>
  542. #include <version>
  543. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  544. # pragma GCC system_header
  545. #endif
  546. #ifdef _LIBCPP_HAS_NO_ATOMIC_HEADER
  547. # error <atomic> is not implemented
  548. #endif
  549. #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
  550. # include <cmath>
  551. # include <compare>
  552. # include <cstdlib>
  553. # include <cstring>
  554. # include <type_traits>
  555. #endif
  556. #endif // _LIBCPP_ATOMIC