36 #ifndef VIGRA_THREADING_HXX
37 #define VIGRA_THREADING_HXX
44 #ifndef VIGRA_SINGLE_THREADED
46 #ifndef VIGRA_NO_STD_THREADING
47 # if defined(__clang__)
48 # if (!__has_include(<thread>) || !__has_include(<mutex>) || !__has_include(<atomic>))
49 # define VIGRA_NO_STD_THREADING
52 # if defined(__GNUC__) && (!defined(_GLIBCXX_HAS_GTHREADS) || !defined(_GLIBCXX_USE_C99_STDINT_TR1) || !defined(_GLIBCXX_USE_SCHED_YIELD))
53 # define VIGRA_NO_STD_THREADING
57 # if defined(_MSC_VER) && _MSC_VER <= 1600
58 # define VIGRA_NO_STD_THREADING
62 #ifdef USE_BOOST_THREAD
63 # include <boost/thread.hpp>
64 # if BOOST_VERSION >= 105300
65 # include <boost/atomic.hpp>
66 # define VIGRA_HAS_ATOMIC 1
68 # define VIGRA_THREADING_NAMESPACE boost
69 #elif defined(VIGRA_NO_STD_THREADING)
70 # error "Your compiler does not support std::thread. If the boost libraries are available, consider running cmake with -DWITH_BOOST_THREAD=1"
76 # define VIGRA_HAS_ATOMIC 1
77 # define VIGRA_THREADING_NAMESPACE std
80 #if defined(_MSC_VER) && !defined(VIGRA_HAS_ATOMIC)
84 namespace vigra {
namespace threading {
88 using VIGRA_THREADING_NAMESPACE::thread;
90 namespace this_thread {
92 using VIGRA_THREADING_NAMESPACE::this_thread::yield;
93 using VIGRA_THREADING_NAMESPACE::this_thread::get_id;
94 using VIGRA_THREADING_NAMESPACE::this_thread::sleep_for;
95 using VIGRA_THREADING_NAMESPACE::this_thread::sleep_until;
101 using VIGRA_THREADING_NAMESPACE::mutex;
102 using VIGRA_THREADING_NAMESPACE::timed_mutex;
103 using VIGRA_THREADING_NAMESPACE::recursive_mutex;
104 using VIGRA_THREADING_NAMESPACE::recursive_timed_mutex;
106 using VIGRA_THREADING_NAMESPACE::lock_guard;
107 using VIGRA_THREADING_NAMESPACE::unique_lock;
109 using VIGRA_THREADING_NAMESPACE::defer_lock_t;
110 using VIGRA_THREADING_NAMESPACE::try_to_lock_t;
111 using VIGRA_THREADING_NAMESPACE::adopt_lock_t;
113 using VIGRA_THREADING_NAMESPACE::defer_lock;
114 using VIGRA_THREADING_NAMESPACE::try_to_lock;
115 using VIGRA_THREADING_NAMESPACE::adopt_lock;
117 using VIGRA_THREADING_NAMESPACE::try_lock;
118 using VIGRA_THREADING_NAMESPACE::lock;
120 using VIGRA_THREADING_NAMESPACE::once_flag;
121 using VIGRA_THREADING_NAMESPACE::call_once;
128 #ifdef VIGRA_HAS_ATOMIC
132 using VIGRA_THREADING_NAMESPACE::atomic_flag;
133 using VIGRA_THREADING_NAMESPACE::atomic;
135 using VIGRA_THREADING_NAMESPACE::atomic_char;
136 using VIGRA_THREADING_NAMESPACE::atomic_schar;
137 using VIGRA_THREADING_NAMESPACE::atomic_uchar;
138 using VIGRA_THREADING_NAMESPACE::atomic_short;
139 using VIGRA_THREADING_NAMESPACE::atomic_ushort;
140 using VIGRA_THREADING_NAMESPACE::atomic_int;
141 using VIGRA_THREADING_NAMESPACE::atomic_uint;
142 using VIGRA_THREADING_NAMESPACE::atomic_long;
143 using VIGRA_THREADING_NAMESPACE::atomic_ulong;
144 using VIGRA_THREADING_NAMESPACE::atomic_llong;
145 using VIGRA_THREADING_NAMESPACE::atomic_ullong;
148 using VIGRA_THREADING_NAMESPACE::atomic_wchar_t;
149 using VIGRA_THREADING_NAMESPACE::atomic_int_least8_t;
150 using VIGRA_THREADING_NAMESPACE::atomic_uint_least8_t;
151 using VIGRA_THREADING_NAMESPACE::atomic_int_least16_t;
152 using VIGRA_THREADING_NAMESPACE::atomic_uint_least16_t;
153 using VIGRA_THREADING_NAMESPACE::atomic_int_least32_t;
154 using VIGRA_THREADING_NAMESPACE::atomic_uint_least32_t;
155 using VIGRA_THREADING_NAMESPACE::atomic_int_least64_t;
156 using VIGRA_THREADING_NAMESPACE::atomic_uint_least64_t;
157 using VIGRA_THREADING_NAMESPACE::atomic_int_fast8_t;
158 using VIGRA_THREADING_NAMESPACE::atomic_uint_fast8_t;
159 using VIGRA_THREADING_NAMESPACE::atomic_int_fast16_t;
160 using VIGRA_THREADING_NAMESPACE::atomic_uint_fast16_t;
161 using VIGRA_THREADING_NAMESPACE::atomic_int_fast32_t;
162 using VIGRA_THREADING_NAMESPACE::atomic_uint_fast32_t;
163 using VIGRA_THREADING_NAMESPACE::atomic_int_fast64_t;
164 using VIGRA_THREADING_NAMESPACE::atomic_uint_fast64_t;
165 using VIGRA_THREADING_NAMESPACE::atomic_intptr_t;
166 using VIGRA_THREADING_NAMESPACE::atomic_uintptr_t;
167 using VIGRA_THREADING_NAMESPACE::atomic_size_t;
168 using VIGRA_THREADING_NAMESPACE::atomic_ptrdiff_t;
169 using VIGRA_THREADING_NAMESPACE::atomic_intmax_t;
170 using VIGRA_THREADING_NAMESPACE::atomic_uintmax_t;
172 using VIGRA_THREADING_NAMESPACE::memory_order;
173 using VIGRA_THREADING_NAMESPACE::memory_order_relaxed;
174 using VIGRA_THREADING_NAMESPACE::memory_order_release;
175 using VIGRA_THREADING_NAMESPACE::memory_order_acquire;
176 using VIGRA_THREADING_NAMESPACE::memory_order_consume;
177 using VIGRA_THREADING_NAMESPACE::memory_order_acq_rel;
178 using VIGRA_THREADING_NAMESPACE::memory_order_seq_cst;
180 using VIGRA_THREADING_NAMESPACE::atomic_thread_fence;
181 using VIGRA_THREADING_NAMESPACE::atomic_signal_fence;
201 #else // VIGRA_HAS_ATOMIC not defined
204 memory_order_relaxed,
205 memory_order_release,
206 memory_order_acquire,
207 memory_order_consume,
208 memory_order_acq_rel,
214 template <
int SIZE=4>
215 struct atomic_long_impl
217 typedef LONG value_type;
219 static long load(value_type
const & val)
226 static void store(value_type & dest,
long val)
232 static long add(value_type & dest,
long val)
234 return InterlockedExchangeAdd(&dest, val);
237 static long sub(value_type & dest,
long val)
239 return InterlockedExchangeAdd(&dest, -val);
242 static bool compare_exchange(value_type & dest,
long & old_val,
long new_val)
244 long check_val = old_val;
245 old_val = InterlockedCompareExchange(&dest, new_val, old_val);
246 return check_val == old_val;
251 struct atomic_long_impl<8>
253 typedef LONGLONG value_type;
255 static long load(value_type
const & val)
262 static void store(value_type & dest,
long val)
268 static long add(value_type & dest,
long val)
270 return InterlockedExchangeAdd64(&dest, val);
273 static long sub(value_type & dest,
long val)
275 return InterlockedExchangeAdd64(&dest, -val);
278 static bool compare_exchange(value_type & dest,
long & old_val,
long new_val)
280 long check_val = old_val;
281 old_val = InterlockedCompareExchange64(&dest, new_val, old_val);
282 return check_val == old_val;
288 template <
int SIZE=4>
289 struct atomic_long_impl
291 typedef long value_type;
293 static long load(value_type
const & val)
296 __sync_synchronize();
300 static void store(value_type & dest,
long val)
302 __sync_synchronize();
306 static long add(value_type & dest,
long val)
308 return __sync_fetch_and_add(&dest, val);
311 static long sub(value_type & dest,
long val)
313 return __sync_fetch_and_sub(&dest, val);
316 static bool compare_exchange(value_type & dest,
long & old_val,
long new_val)
318 long check_val = old_val;
319 old_val = __sync_val_compare_and_swap(&dest, old_val, new_val);
320 return check_val == old_val;
328 typedef atomic_long_impl<sizeof(long)>::value_type value_type;
330 atomic_long(
long v = 0)
334 atomic_long & operator=(
long val)
340 long load(memory_order = memory_order_seq_cst)
const
342 return atomic_long_impl<sizeof(long)>::load(value_);
345 void store(
long v, memory_order = memory_order_seq_cst)
347 atomic_long_impl<sizeof(long)>::store(value_, v);
350 long fetch_add(
long v, memory_order = memory_order_seq_cst)
355 long fetch_sub(
long v, memory_order = memory_order_seq_cst)
360 bool compare_exchange_strong(
long & old_val,
long new_val, memory_order = memory_order_seq_cst)
362 return atomic_long_impl<sizeof(long)>::compare_exchange(value_, old_val, new_val);
365 bool compare_exchange_weak(
long & old_val,
long new_val, memory_order = memory_order_seq_cst)
367 return atomic_long_impl<sizeof(long)>::compare_exchange(value_, old_val, new_val);
373 #endif // VIGRA_HAS_ATOMIC
377 #undef VIGRA_THREADING_NAMESPACE
379 #endif // not VIGRA_SINGLE_THREADED
381 #endif // VIGRA_THREADING_HXX