72590c8c5bc91c682f7a48bd32f8e010da0dd4cb
[vlc.git] / include / vlc_atomic.h
1 /*****************************************************************************
2  * vlc_atomic.h:
3  *****************************************************************************
4  * Copyright (C) 2010 RĂ©mi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifndef VLC_ATOMIC_H
22 # define VLC_ATOMIC_H
23
24 /**
25  * \file
26  * Atomic operations do not require locking, but they are not very powerful.
27  */
28
29 # ifndef __cplusplus
30 #  if (__STDC_VERSION__ >= 201112L) && defined(__STDC_NO_ATOMICS__)
31 #   error Atomic operations required!
32 #  endif
33 /*** Native C11 atomics ***/
34 #  include <stdatomic.h>
35
36 # else /* C++ */
37 /*** Native C++11 atomics ***/
38 #   include <atomic>
39 using std::atomic_is_lock_free;
40 using std::atomic_init;
41 using std::atomic_store;
42 using std::atomic_store_explicit;
43 using std::atomic_load;
44 using std::atomic_load_explicit;
45 using std::atomic_exchange;
46 using std::atomic_exchange_explicit;
47 using std::atomic_compare_exchange_strong;
48 using std::atomic_compare_exchange_strong_explicit;
49 using std::atomic_compare_exchange_weak;
50 using std::atomic_compare_exchange_weak_explicit;
51 using std::atomic_fetch_add;
52 using std::atomic_fetch_add_explicit;
53 using std::atomic_fetch_sub;
54 using std::atomic_fetch_sub_explicit;
55 using std::atomic_fetch_or;
56 using std::atomic_fetch_or_explicit;
57 using std::atomic_fetch_xor;
58 using std::atomic_fetch_xor_explicit;
59 using std::atomic_fetch_and;
60 using std::atomic_fetch_and_explicit;
61 using std::atomic_thread_fence;
62 using std::atomic_signal_fence;
63
64 using std::memory_order;
65 using std::memory_order_relaxed;
66 using std::memory_order_consume;
67 using std::memory_order_release;
68 using std::memory_order_acq_rel;
69 using std::memory_order_seq_cst;
70
71 using std::atomic_flag;
72 typedef std::atomic<bool> atomic_bool;
73 typedef std::atomic<char> atomic_char;
74 typedef std::atomic<signed char> atomic_schar;
75 typedef std::atomic<unsigned char> atomic_uchar;
76 typedef std::atomic<short> atomic_short;
77 typedef std::atomic<unsigned short> atomic_ushort;
78 typedef std::atomic<int> atomic_int;
79 typedef std::atomic<unsigned int> atomic_uint;
80 typedef std::atomic<long> atomic_long;
81 typedef std::atomic<unsigned long> atomic_ulong;
82 typedef std::atomic<long long> atomic_llong;
83 typedef std::atomic<unsigned long long> atomic_ullong;
84 typedef std::atomic<char16_t> atomic_char16_t;
85 typedef std::atomic<char32_t> atomic_char32_t;
86 typedef std::atomic<wchar_t> atomic_wchar_t;
87 typedef std::atomic<int_least8_t> atomic_int_least8_t;
88 typedef std::atomic<uint_least8_t> atomic_uint_least8_t;
89 typedef std::atomic<int_least16_t> atomic_int_least16_t;
90 typedef std::atomic<uint_least16_t> atomic_uint_least16_t;
91 typedef std::atomic<int_least32_t> atomic_int_least32_t;
92 typedef std::atomic<uint_least32_t> atomic_uint_least32_t;
93 typedef std::atomic<int_least64_t> atomic_int_least64_t;
94 typedef std::atomic<uint_least64_t> atomic_uint_least64_t;
95 typedef std::atomic<int_fast8_t> atomic_int_fast8_t;
96 typedef std::atomic<uint_fast8_t> atomic_uint_fast8_t;
97 typedef std::atomic<int_fast16_t> atomic_int_fast16_t;
98 typedef std::atomic<uint_fast16_t> atomic_uint_fast16_t;
99 typedef std::atomic<int_fast32_t> atomic_int_fast32_t;
100 typedef std::atomic<uint_fast32_t> atomic_uint_fast32_t;
101 typedef std::atomic<int_fast64_t> atomic_int_fast64_t;
102 typedef std::atomic<uint_fast64_t> atomic_uint_fast64_t;
103 typedef std::atomic<intptr_t> atomic_intptr_t;
104 typedef std::atomic<uintptr_t> atomic_uintptr_t;
105 typedef std::atomic<size_t> atomic_size_t;
106 typedef std::atomic<ptrdiff_t> atomic_ptrdiff_t;
107 typedef std::atomic<intmax_t> atomic_intmax_t;
108 typedef std::atomic<uintmax_t> atomic_uintmax_t;
109
110 # endif /* C++ */
111
112 typedef atomic_uint_least32_t vlc_atomic_float;
113
114 static inline void vlc_atomic_init_float(vlc_atomic_float *var, float f)
115 {
116     union { float f; uint32_t i; } u;
117     u.f = f;
118     atomic_init(var, u.i);
119 }
120
121 /** Helper to retrieve a single precision from an atom. */
122 static inline float vlc_atomic_load_float(vlc_atomic_float *atom)
123 {
124     union { float f; uint32_t i; } u;
125     u.i = atomic_load(atom);
126     return u.f;
127 }
128
129 /** Helper to store a single precision into an atom. */
130 static inline void vlc_atomic_store_float(vlc_atomic_float *atom, float f)
131 {
132     union { float f; uint32_t i; } u;
133     u.f = f;
134     atomic_store(atom, u.i);
135 }
136
137 #endif