mingw/Thread.hh
Go to the documentation of this file.
1 
42 #ifndef CRL_MULTISENSE_THREAD_HH
43 #define CRL_MULTISENSE_THREAD_HH
44 
45 #ifndef WIN32_LEAN_AND_MEAN
46 #define WIN32_LEAN_AND_MEAN 1
47 #endif
48 #include <windows.h>
49 
50 #include <stdint.h>
51 #include <errno.h>
52 #include <string.h>
53 
54 #include <vector>
55 #include <deque>
56 
58 
59 #include "utility/Exception.hh"
60 
61 namespace crl {
62 namespace multisense {
63 namespace details {
64 namespace utility {
65 
66 //
67 // Forward declarations.
68 
69 class ScopedLock;
70 
71 //
72 // A simple class to wrap pthread creation and joining
73 
74 class Thread {
75 public:
76 
77  static CRL_CONSTEXPR uint32_t FLAGS_DETACH = (1 << 0);
78 
79  Thread(LPTHREAD_START_ROUTINE functionP,
80  void *contextP=NULL,
81  uint32_t flags=0,
82  int32_t scheduler=-1,
83  int32_t priority=0) : m_flags(flags) {
84 
85  //
86  // -1 means the user wants default scheduling behavior
87 
88  if (-1 != scheduler) {
89 
90  //
91  // Set our scheduling policy
92 
93  if (scheduler != 0 /* SCHED_OTHER */)
94  CRL_EXCEPTION("This platform only supports SCHED_OTHER",0);
95 
96  if (priority != 0)
97  CRL_EXCEPTION("Priority can not be set at this time.",0);
98  }
99 
100  //
101  // Finally, create the thread
102 
103  m_threadHandle = CreateThread (NULL, 0, functionP, contextP, 0, &m_threadId);
104  if (m_threadHandle == NULL)
105  CRL_EXCEPTION("CreateThread() failed: %d", GetLastError());
106 
107  //
108  // Automatically detach, if asked to do so
109 
110  if (FLAGS_DETACH & m_flags)
111  {
112  CloseHandle (m_threadHandle);
113  }
114  };
115 
117  if (!(m_flags & FLAGS_DETACH) &&
118  0 != WaitForSingleObject(m_threadHandle, INFINITE))
119  CRL_DEBUG("WaitForSingleObject() failed: %d\n", (int)GetLastError());
120  };
121 
122 private:
123 
124  uint32_t m_flags;
125  DWORD m_threadId;
127 };
128 
129 //
130 // A simple mutex class
131 
132 class Mutex {
133 public:
134  friend class ScopedLock;
135 
136  Mutex() {
137  InitializeCriticalSection(&m_mutex);
138  }
139 
140  ~Mutex() {
141  DeleteCriticalSection(&m_mutex);
142  };
143 
144 private:
145  CRITICAL_SECTION m_mutex;
146 };
147 
148 //
149 // A simple scoped lock class
150 
151 class ScopedLock
152 {
153 public:
154 
155  ScopedLock(Mutex& mutex) {
156  this->lock(&mutex.m_mutex);
157  };
158 
159  ScopedLock(CRITICAL_SECTION *lockP) {
160  this->lock(lockP);
161  };
162 
163  ScopedLock(CRITICAL_SECTION& lock) {
164  this->lock(&lock);
165  };
166 
168  LeaveCriticalSection(m_lockP);
169  };
170 
171 private:
172 
173  void lock(CRITICAL_SECTION *lockP) {
174  m_lockP = lockP;
175  EnterCriticalSection(m_lockP);
176  };
177 
178  CRITICAL_SECTION *m_lockP;
179 };
180 
181 // A futex-based semaphore.
182 //
183 // This implementation does not work across processes.
184 
185 class Semaphore {
186 public:
187 
188  //
189  // Wait for a post (decrement). If thread contention,
190  // we may wake up, but be unable to snatch
191  // the bait.. hence the while loop.
192 
193  bool wait() {
194  do {
195  if (0 == wait_(INFINITE))
196  return true;
197  } while (1);
198  };
199 
200  //
201  // Wait for a post, retrying until timeout
202 
203  bool timedWait(const double& timeout) {
204 
205  if (timeout < 0.0)
206  CRL_EXCEPTION("invalid timeout: %f", timeout);
207 
208  do {
209  int32_t ret = wait_((DWORD)(timeout * 1000));
210 
211  if (0 == ret)
212  return true;
213  else if (ETIMEDOUT == ret)
214  return false;
215 
216  } while (1);
217  };
218 
219  //
220  // Post to the semaphore (increment.) Here we
221  // signal the futex to wake up any waiters.
222 
223  bool post() {
224 
225  return ReleaseSemaphore(m_handle, 1, NULL) != FALSE;
226 
227  };
228 
229  //
230  // Decrement the semaphore to zero in one-shot.. may
231  // fail with thread contention, returns true if
232  // successful
233 
234  bool clear() {
235  while(WaitForSingleObject (m_handle, 0) == WAIT_OBJECT_0)
236  {
237  }
238  return true;
239  };
240 
241  int32_t waiters () { return m_waiters; };
242  bool decrement() { return wait(); };
243  bool increment() { return post(); };
244 
245  Semaphore(LONG max=0) :
246  m_waiters(0)
247  {
248  m_handle = CreateSemaphore (NULL, 0, (max == 0 || max > LONG_MAX) ? LONG_MAX : max, NULL);
249  if (m_handle == NULL)
250  CRL_EXCEPTION ("CreateSemaphore() failed: %d\n", GetLastError());
251  }
252 
254  {
255  if (m_handle != NULL)
256  CloseHandle (m_handle);
257  }
258 
259 private:
260 
261  //
262  // This actually does the synchronized decrement if possible, and goes
263  // to sleep on the futex if not.
264 
265  inline int32_t wait_(DWORD ts=INFINITE) {
266  InterlockedIncrement (&m_waiters);
267  const int32_t ret = WaitForSingleObject (m_handle, ts);
268  InterlockedDecrement (&m_waiters);
269 
270  if (ret == WAIT_OBJECT_0)
271  return 0;
272  else if (ret == WAIT_TIMEOUT)
273  return ETIMEDOUT;
274  else
275  return EAGAIN;
276  };
277 
278  HANDLE m_handle;
279  LONG m_waiters;
280 };
281 
282 //
283 // A templatized variable signaler
284 
285 template<class T> class WaitVar {
286 public:
287 
288  void post(const T& data) {
289  {
290  ScopedLock lock(m_lock);
291  m_val = data;
292  }
293  m_sem.post();
294  };
295 
296  bool wait(T& data) {
297  m_sem.wait();
298  {
299  ScopedLock lock(m_lock);
300  data = m_val;
301  }
302  return true;
303  };
304 
305  bool timedWait(T& data,
306  const double& timeout) {
307 
308  if (false == m_sem.timedWait(timeout))
309  return false;
310  {
311  ScopedLock lock(m_lock);
312  data = m_val;
313  }
314  return true;
315  }
316 
317  //
318  // Use a semaphore with max value of 1. The WaitVar will
319  // either be in a signaled state, or not.
320 
321  WaitVar() : m_val(),
322  m_lock(),
323  m_sem(1) {};
324 
325 private:
326 
327  T m_val;
328  Mutex m_lock;
330 };
331 
332 //
333 // A templatized wait queue
334 
335 template <class T> class WaitQueue {
336 public:
337 
338  void post(const T& data) {
339  bool postSem=true;
340  {
341  ScopedLock lock(m_lock);
342 
343  //
344  // Limit deque size, if requested
345 
346  if (m_maximum > 0 &&
347  m_maximum == m_queue.size()) {
348 
349  //
350  // If at max entries, we will pop_front the oldest,
351  // push_back the newest, and leave the semaphore alone
352 
353  m_queue.pop_front();
354  postSem = false;
355  }
356 
357  m_queue.push_back(data);
358  }
359  if (postSem)
360  m_sem.post();
361  };
362 
363  void kick() {
364  m_sem.post();
365  };
366 
367  bool wait(T& data) {
368  m_sem.wait();
369  {
370  ScopedLock lock(m_lock);
371 
372  if (0 == m_queue.size())
373  return false;
374  else {
375  data = m_queue.front();
376  m_queue.pop_front();
377  return true;
378  }
379  }
380  }
381 
382  uint32_t waiters() {
383  return m_sem.waiters();
384  };
385 
386  uint32_t size() {
387  ScopedLock lock(m_lock);
388  return m_queue.size();
389  }
390 
391  void clear() {
392  ScopedLock lock(m_lock);
393  m_queue.clear();
394  while(false == m_sem.clear());
395  }
396 
397  WaitQueue(std::size_t max=0) :
398  m_maximum(max) {};
399 
400 private:
401 
402  const std::size_t m_maximum;
403  std::deque<T> m_queue;
404  Mutex m_lock;
406 };
407 
408 }}}} // namespaces
409 
410 #endif /* #ifndef CRL_MULTISENSE_THREAD_HH */
crl::multisense::details::utility::Semaphore::~Semaphore
~Semaphore()
Definition: mingw/Thread.hh:253
crl::multisense::details::utility::Thread::m_threadId
DWORD m_threadId
Definition: mingw/Thread.hh:125
crl::multisense::details::utility::WaitQueue::size
uint32_t size()
Definition: mingw/Thread.hh:386
crl::multisense::details::utility::Mutex
Definition: linux/Thread.hh:144
crl::multisense::details::utility::Thread::Thread
Thread(LPTHREAD_START_ROUTINE functionP, void *contextP=NULL, uint32_t flags=0, int32_t scheduler=-1, int32_t priority=0)
Definition: mingw/Thread.hh:79
crl::multisense::details::utility::Semaphore::decrement
bool decrement()
Definition: mingw/Thread.hh:242
CRL_DEBUG
#define CRL_DEBUG(fmt,...)
Definition: Exception.hh:71
Exception.hh
crl::multisense::details::utility::WaitQueue::wait
bool wait(T &data)
Definition: mingw/Thread.hh:367
crl::multisense::details::utility::WaitQueue::m_maximum
const std::size_t m_maximum
Definition: linux/Thread.hh:436
crl::multisense::details::utility::WaitVar
Definition: linux/Thread.hh:323
crl::multisense::details::utility::WaitQueue::m_sem
Semaphore m_sem
Definition: linux/Thread.hh:443
CRL_CONSTEXPR
#define CRL_CONSTEXPR
Definition: Legacy/include/MultiSense/details/utility/Portability.hh:49
crl::multisense::details::utility::Semaphore::wait
bool wait()
Definition: mingw/Thread.hh:193
crl::multisense::details::utility::Semaphore::Semaphore
Semaphore(LONG max=0)
Definition: mingw/Thread.hh:245
crl::multisense::details::utility::WaitQueue::kick
void kick()
Definition: mingw/Thread.hh:363
crl::multisense::details::utility::Semaphore::clear
bool clear()
Definition: mingw/Thread.hh:234
crl::multisense::details::utility::WaitQueue::m_lock
Mutex m_lock
Definition: linux/Thread.hh:442
crl::multisense::details::utility::Mutex::~Mutex
~Mutex()
Definition: mingw/Thread.hh:140
Portability.hh
crl::multisense::details::utility::Semaphore::wait_
int32_t wait_(const struct timespec *tsP=NULL)
Definition: linux/Thread.hh:286
crl::multisense::details::utility::WaitQueue::waiters
uint32_t waiters()
Definition: mingw/Thread.hh:382
CRL_EXCEPTION
#define CRL_EXCEPTION(fmt,...)
Definition: Exception.hh:85
crl
Definition: Legacy/details/channel.cc:61
crl::multisense::details::utility::ScopedLock::lock
void lock(CRITICAL_SECTION *lockP)
Definition: mingw/Thread.hh:173
crl::multisense::details::utility::WaitVar::wait
bool wait(T &data)
Definition: mingw/Thread.hh:296
crl::multisense::details::utility::WaitVar::WaitVar
WaitVar()
Definition: mingw/Thread.hh:321
crl::multisense::details::utility::Semaphore::timedWait
bool timedWait(const double &timeout)
Definition: mingw/Thread.hh:203
crl::multisense::details::utility::WaitQueue::clear
void clear()
Definition: mingw/Thread.hh:391
crl::multisense::details::utility::WaitVar::m_lock
Mutex m_lock
Definition: linux/Thread.hh:366
crl::multisense::details::utility::Thread::FLAGS_DETACH
static CRL_CONSTEXPR uint32_t FLAGS_DETACH
Definition: linux/Thread.hh:76
crl::multisense::details::utility::WaitQueue::WaitQueue
WaitQueue(std::size_t max=0)
Definition: mingw/Thread.hh:397
crl::multisense::details::utility::Semaphore::waiters
int32_t waiters()
Definition: mingw/Thread.hh:241
crl::multisense::details::utility::Semaphore::post
bool post()
Definition: mingw/Thread.hh:223
crl::multisense::details::utility::ScopedLock::~ScopedLock
~ScopedLock()
Definition: mingw/Thread.hh:167
crl::multisense::details::utility::Semaphore::wait_
int32_t wait_(DWORD ts=INFINITE)
Definition: mingw/Thread.hh:265
crl::multisense::details::utility::Thread::m_threadHandle
HANDLE m_threadHandle
Definition: mingw/Thread.hh:126
crl::multisense::details::utility::Thread::m_flags
uint32_t m_flags
Definition: linux/Thread.hh:133
crl::multisense::details::utility::WaitVar::m_val
T m_val
Definition: linux/Thread.hh:361
crl::multisense::details::utility::Mutex::Mutex
Mutex()
Definition: mingw/Thread.hh:136
multisense
Definition: factory.cc:39
crl::multisense::details::utility::ScopedLock::lock
void lock(pthread_mutex_t *lockP)
Definition: linux/Thread.hh:187
crl::multisense::details::utility::Semaphore::increment
bool increment()
Definition: mingw/Thread.hh:243
crl::multisense::details::utility::WaitVar::m_sem
Semaphore m_sem
Definition: linux/Thread.hh:367
crl::multisense::details::utility::WaitVar::post
void post(const T &data)
Definition: mingw/Thread.hh:288
crl::multisense::details::utility::Semaphore
Definition: linux/Thread.hh:199
crl::multisense::details::utility::Thread::~Thread
~Thread()
Definition: mingw/Thread.hh:116
crl::multisense::details::utility::ScopedLock
Definition: linux/Thread.hh:165
crl::multisense::details::utility::ScopedLock::ScopedLock
ScopedLock(Mutex &mutex)
Definition: mingw/Thread.hh:155
crl::multisense::details::utility::ScopedLock::ScopedLock
ScopedLock(CRITICAL_SECTION &lock)
Definition: mingw/Thread.hh:163
crl::multisense::details::utility::Semaphore::m_handle
HANDLE m_handle
Definition: mingw/Thread.hh:276
crl::multisense::details::utility::ScopedLock::m_lockP
pthread_mutex_t * m_lockP
Definition: linux/Thread.hh:190
crl::multisense::details::utility::Mutex::m_mutex
pthread_mutex_t m_mutex
Definition: linux/Thread.hh:156
crl::multisense::details::utility::WaitQueue::m_queue
std::deque< T > m_queue
Definition: linux/Thread.hh:441
crl::multisense::details::utility::Semaphore::m_waiters
aligned_int32_t m_waiters
Definition: linux/Thread.hh:317
crl::multisense::details::utility::WaitQueue::post
void post(const T &data)
Definition: mingw/Thread.hh:338
crl::multisense::details::utility::ScopedLock::ScopedLock
ScopedLock(CRITICAL_SECTION *lockP)
Definition: mingw/Thread.hh:159
crl::multisense::details::utility::WaitVar::timedWait
bool timedWait(T &data, const double &timeout)
Definition: mingw/Thread.hh:305


multisense_lib
Author(s):
autogenerated on Thu Apr 17 2025 02:49:09