ROSE  0.9.9.109
Synchronization.h
1 // WARNING: Changes to this file must be contributed back to Sawyer or else they will
2 // be clobbered by the next update from Sawyer. The Sawyer repository is at
3 // https://github.com/matzke1/sawyer.
4 
5 
6 
7 
8 #ifndef Sawyer_Synchronization_H
9 #define Sawyer_Synchronization_H
10 
11 #include <Sawyer/Sawyer.h>
12 
13 #if SAWYER_MULTI_THREADED
14  // It appears as though a certain version of GNU libc interacts badly with C++03 GCC and LLVM compilers. Some system header
15  // file defines _XOPEN_UNIX as "1" and __UINTPTR_TYPE__ as "unsigned long int" but doesn't provide a definition for
16  // "uintptr_t". This triggers a compilation error in <boost/atomic/atomic.hpp> for boost-1.54 because it assumes that
17  // "uintptr_t" is available based on the preprocessor macros and the included files. These errors occur (at a minimum) on
18  // Debian 8.2 and 8.3 using C++03 mode of gcc-4.8.4, gcc-4.9.2, or llvm-3.5.
19  #include <boost/version.hpp>
20  #if __cplusplus < 201103L && BOOST_VERSION == 105400
21  #include <stdint.h> // must be included before <boost/thread.hpp>
22  #endif
23 
24  #include <boost/thread.hpp>
25  #include <boost/thread/barrier.hpp>
26  #include <boost/thread/condition_variable.hpp>
27  #include <boost/thread/mutex.hpp>
28  #include <boost/thread/locks.hpp>
29  #include <boost/thread/once.hpp>
30  #include <boost/thread/recursive_mutex.hpp>
31 #endif
32 
33 namespace Sawyer {
34 
39 struct MultiThreadedTag {};
40 
46 
47 // Used internally as a mutex in a single-threaded environment. Although it doesn't make sense to be able lock or unlock a
48 // mutex in a single-threaded environment, incrementing a data member for each unlock might be useful and it works in
49 // conjunction with NullLockGuard to prevent compilers from warning about unused variables which, at least in the
50 // multi-threaded environment, are used only for their RAII side effects.
51 class NullMutex {
52  size_t n;
53 public:
54  NullMutex(): n(0) {}
55  void lock() {}
56  void unlock() { ++n; }
57  bool try_lock() { return true; }
58 };
59 
60 // Used internally as a lock guard in a single-threaded environment.
62  NullMutex &mutex_;
63 public:
65  : mutex_(m) {
66  lock();
67  }
68  ~NullLockGuard() {
69  unlock();
70  }
71  void lock() {
72  mutex_.lock();
73  }
74  void unlock() {
75  mutex_.unlock();
76  }
77 };
78 
79 // Used internally as a barrier in a single-threaded environment.
80 class NullBarrier {
81 public:
82  explicit NullBarrier(unsigned count) {
83  if (count > 1)
84  throw std::runtime_error("barrier would deadlock");
85  }
86  bool wait() {
87  return true;
88  }
89 };
90 
92 template<typename Mutex>
93 class LockGuard2 {
94  Mutex &m1_, &m2_;
95 public:
96  LockGuard2(Mutex &m1, Mutex &m2): m1_(m1), m2_(m2) {
97 #if SAWYER_MULTI_THREADED
98  boost::lock(m1, m2);
99 #endif
100  }
101  ~LockGuard2() {
102  m1_.unlock();
103  m2_.unlock();
104  }
105 };
106 
107 template<>
109 public:
111 };
112 
114 template<typename SyncTag>
116 
117 template<>
119 #if SAWYER_MULTI_THREADED
120  enum { SUPPORTED = 1 };
121  typedef boost::mutex Mutex;
122  typedef boost::recursive_mutex RecursiveMutex;
123  typedef boost::lock_guard<boost::mutex> LockGuard;
124  typedef boost::unique_lock<boost::mutex> UniqueLock;
125  typedef boost::lock_guard<boost::recursive_mutex> RecursiveLockGuard;
126  typedef boost::condition_variable_any ConditionVariable;
127  typedef boost::barrier Barrier;
128 #else
129  enum { SUPPORTED = 0 };
130  typedef NullMutex Mutex;
131  typedef NullMutex RecursiveMutex;
132  typedef NullLockGuard LockGuard;
133  typedef NullLockGuard UniqueLock;
134  typedef NullLockGuard RecursiveLockGuard;
135  //typedef ... ConditionVariable; -- does not make sense to use this in a single-threaded program
136  typedef NullBarrier Barrier;
137 #endif
139 };
140 
141 
142 template<>
144  enum { SUPPORTED = 0 };
145  typedef NullMutex Mutex;
146  typedef NullMutex RecursiveMutex;
147  typedef NullLockGuard LockGuard;
148  typedef NullLockGuard UniqueLock;
150  //typedef ... ConditionVariable; -- does not make sense to use this in a single-threaded program
151  typedef NullBarrier Barrier;
153 };
154 
155 // Used internally.
156 SAWYER_EXPORT SAWYER_THREAD_TRAITS::RecursiveMutex& bigMutex();
157 
163 SAWYER_EXPORT size_t fastRandomIndex(size_t n);
164 
165 } // namespace
166 #endif
size_t fastRandomIndex(size_t n)
Thread-safe random number generator.
Locks multiple mutexes.
Name space for the entire library.
Definition: Access.h:11
Tag indicating that an algorithm or API should assume multiple threads.
Traits for thread synchronization.
Tag indicating that an algorithm or API can assume only a single thread.