xsens_mutex.h
Go to the documentation of this file.
1 
2 // Copyright (c) 2003-2021 Xsens Technologies B.V. or subsidiaries worldwide.
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions, and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions, and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the names of the copyright holders nor the names of their contributors
16 // may be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
24 // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
26 // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.THE LAWS OF THE NETHERLANDS
28 // SHALL BE EXCLUSIVELY APPLICABLE AND ANY DISPUTES SHALL BE FINALLY SETTLED UNDER THE RULES
29 // OF ARBITRATION OF THE INTERNATIONAL CHAMBER OF COMMERCE IN THE HAGUE BY ONE OR MORE
30 // ARBITRATORS APPOINTED IN ACCORDANCE WITH SAID RULES.
31 //
32 
33 
34 // Copyright (c) 2003-2021 Xsens Technologies B.V. or subsidiaries worldwide.
35 // All rights reserved.
36 //
37 // Redistribution and use in source and binary forms, with or without modification,
38 // are permitted provided that the following conditions are met:
39 //
40 // 1. Redistributions of source code must retain the above copyright notice,
41 // this list of conditions, and the following disclaimer.
42 //
43 // 2. Redistributions in binary form must reproduce the above copyright notice,
44 // this list of conditions, and the following disclaimer in the documentation
45 // and/or other materials provided with the distribution.
46 //
47 // 3. Neither the names of the copyright holders nor the names of their contributors
48 // may be used to endorse or promote products derived from this software without
49 // specific prior written permission.
50 //
51 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
52 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
53 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
54 // THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 // SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
56 // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
58 // TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
59 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.THE LAWS OF THE NETHERLANDS
60 // SHALL BE EXCLUSIVELY APPLICABLE AND ANY DISPUTES SHALL BE FINALLY SETTLED UNDER THE RULES
61 // OF ARBITRATION OF THE INTERNATIONAL CHAMBER OF COMMERCE IN THE HAGUE BY ONE OR MORE
62 // ARBITRATORS APPOINTED IN ACCORDANCE WITH SAID RULES.
63 //
64 
65 #ifndef XSENS_MUTEX_H
66 #define XSENS_MUTEX_H
67 
68 #include <cstdint>
69 #include <atomic>
70 #include <xstypes/xsthread.h>
71 #include <xstypes/xstimestamp.h>
72 #include <deque>
73 
74 #ifndef __GNUC__
75  #pragma warning(disable: 4127)
76 #endif
77 
78 namespace xsens
79 {
80 // by setting this to 1 you will enable timeout checks on the locks, see xsens_math_throw.cpp for the implementations
81 #if 0 && defined(XSENS_DEBUG)
82 namespace DebugTools
83 {
84 class TimeoutChecker
85 {
86  XsTimeStamp m_tStart;
87  int m_timeout;
88  char m_category;
89 public:
90  void* m_lock;
91 
92  TimeoutChecker(char category = 'l', void* lock = nullptr);
93  ~TimeoutChecker()
94  {
95  stop();
96  }
97  inline void start(void* lock)
98  {
99  if (lock && !m_lock)
100  m_lock = lock;
101  m_tStart = XsTimeStamp::now();
102  }
103  inline void stop()
104  {
105  if (m_tStart.msTime() && (XsTimeStamp::now() - m_tStart).msTime() >= m_timeout)
106  warning((XsTimeStamp::now() - m_tStart).msTime());
107  m_tStart = 0;
108  }
109  void warning(int64_t);
110 };
111 }
112 #define CHECK_LOCK_DEFINE() mutable DebugTools::TimeoutChecker m_tcCheck
113 #define CHECK_LOCK_ACQUIRE() volatile DebugTools::TimeoutChecker tcAcq('a', this); m_tcCheck.start(this)
114 #define CHECK_LOCK_RELEASE() m_tcCheck.stop(); volatile DebugTools::TimeoutChecker tcRel('r', this)
115 #define TIMEOUTCHECKER_DEFINED 1
116 #else
117 #define CHECK_LOCK_DEFINE() typedef void IgnoredLockDefine
118 #define CHECK_LOCK_ACQUIRE() ((void)0)
119 #define CHECK_LOCK_RELEASE() ((void)0)
120 #define TIMEOUTCHECKER_DEFINED 0
121 #endif
122 
123 class Lock;
124 class LockReadWrite;
125 class LockSuspendable;
126 class WaitCondition;
128 
132 class Mutex
133 {
134 private:
135 #if !XSENS_USE_POSIX_LOCKING
136  CRITICAL_SECTION m_mutex;
137 #else
138  pthread_mutexattr_t m_attr;
139  pthread_mutex_t m_mutex;
140 #endif
142  volatile std::atomic_int m_lockCount;
143  friend class Lock;
144  friend class WaitCondition;
145 public:
147  : m_lockedBy(0)
148  , m_lockCount(0)
149  {
150 #if !XSENS_USE_POSIX_LOCKING
151  ::InitializeCriticalSection(&m_mutex);
152 #else
153  // this is required to get the same behaviour we have in windows
154  pthread_mutexattr_init(&m_attr);
155  pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_RECURSIVE);
156  pthread_mutex_init(&m_mutex, &m_attr);
157 #endif
158  }
160  {
161  assert(m_lockCount == 0);
162  assert(m_lockedBy == 0);
163 #if !XSENS_USE_POSIX_LOCKING
164  ::DeleteCriticalSection(&m_mutex);
165 #else
166  pthread_mutex_destroy(&m_mutex);
167  pthread_mutexattr_destroy(&m_attr);
168 #endif
169  }
170  Mutex(Mutex const&) = delete;
171  Mutex& operator=(Mutex const&) = delete;
172  Mutex(Mutex&&) = delete;
173  Mutex& operator=(Mutex&&) = delete;
174 
178  inline bool claimMutex()
179  {
180 #if !XSENS_USE_POSIX_LOCKING
181  ::EnterCriticalSection(&m_mutex);
182 #else
183  pthread_mutex_lock(&m_mutex);
184 #endif
185  ++m_lockCount;
187  return true;
188  }
189 
193  inline bool releaseMutex()
194  {
195  if (!--m_lockCount)
196  m_lockedBy = 0;
197 #if !XSENS_USE_POSIX_LOCKING
198  ::LeaveCriticalSection(&m_mutex);
199 #else
200  pthread_mutex_unlock(&m_mutex);
201 #endif
202  return true;
203  }
204 
208  inline bool tryClaimMutex()
209  {
210  // *CriticalSection returns true on success, pthread_* returns 0 on success.
211 #if !XSENS_USE_POSIX_LOCKING
212  if (::TryEnterCriticalSection(&m_mutex))
213 #else
214  if (pthread_mutex_trylock(&m_mutex) == 0)
215 #endif
216  {
217  ++m_lockCount;
219  return true;
220  }
221  return false;
222  }
223 #ifdef XSENS_DEBUG
224  // this function is only intended as a debug function for use in assert statements
225  inline bool haveLock() const
226  {
227  return m_lockedBy == xsGetCurrentThreadId();
228  }
229 #endif
230 
233  inline bool isLocked() const volatile
234  {
235  return m_lockCount > 0;
236  }
237 };
238 
239 
249 {
250 private:
252  volatile std::atomic_int m_writeRef;
253  volatile std::atomic<XsThreadId> m_writeLocked;
254  volatile std::atomic_int m_writeLocksPending;
256 
259  friend class LockReadWrite;
260  MutexReadWrite(MutexReadWrite const&) = delete;
261  MutexReadWrite& operator=(MutexReadWrite const&) = delete;
262  MutexReadWrite(MutexReadWrite&&) = delete;
264 
265 public:
266  inline MutexReadWrite()
267  : m_writeRef(0)
268  , m_writeLocked(0)
270  {
271  m_readLockMax = 32;
273  m_readLockCount = 0;
274  }
276  {
277  delete[] m_readLocked;
278  }
279 private:
280  inline void addReadLock(XsThreadId cid)
281  {
283  {
285  XsThreadId* tmp = new XsThreadId[m_readLockMax];
286  memcpy(tmp, m_readLocked, ((unsigned int) m_readLockCount)*sizeof(XsThreadId));
287  delete[] m_readLocked;
288  m_readLocked = tmp;
289  }
290  m_readLocked[m_readLockCount++] = cid;
291  }
292 
293  inline void enterAtomic()
294  {
296  }
297 
298  inline void leaveAtomic()
299  {
301  }
302 
303  inline bool claimMutex(bool write)
304  {
306  // write lock
307  if (write)
308  {
309  enterAtomic();
311  while (1)
312  {
313  bool readFail = false;
314  if (m_writeLocked == 0)
315  {
316  for (int i = 0; i < m_readLockCount; ++i)
317  {
318  if (m_readLocked[i] != cid)
319  {
320  readFail = true;
321  break;
322  }
323  }
324  }
325 
326  if (m_writeLocked != cid && (m_writeLocked != 0 || readFail))
327  {
328  leaveAtomic();
329  xsYield(); // wait for other locks to end
330  enterAtomic();
331  }
332  else
333  {
334  ++m_writeRef;
336  m_writeLocked = cid;
337  leaveAtomic();
338  return true;
339  }
340  }
341  }
342  // read lock
343  else
344  {
345  while (true)
346  {
347  enterAtomic();
348  bool readGot = false;
349  if ((m_writeLocked == 0 && m_writeLocksPending == 0) || m_writeLocked == cid)
350  readGot = true;
351  else
352  for (int i = 0; i < m_readLockCount; ++i)
353  if (m_readLocked[i] == cid)
354  {
355  readGot = true;
356  break;
357  }
358 
359  if (readGot)
360  {
361  addReadLock(cid);
362  leaveAtomic();
363  return true;
364  }
365  leaveAtomic();
366  // wait for write lock to end
367  xsYield();
368  }
369  }
370  }
371 
373  inline bool downgradeToRead()
374  {
376  enterAtomic();
377  if (m_writeLocked == cid)
378  {
379  if (--m_writeRef == 0)
380  m_writeLocked = 0;
381  addReadLock(cid);
382  leaveAtomic();
383  return true;
384  }
385  leaveAtomic();
386  return false;
387  }
388 
389  inline bool releaseMutex(bool write)
390  {
392  enterAtomic();
393  if (write)
394  {
395  if (m_writeLocked == cid)
396  {
397  if (--m_writeRef == 0)
398  m_writeLocked = 0;
399  }
400  else
401  {
402  leaveAtomic();
403  return false;
404  }
405  }
406  else
407  {
408  if (m_readLockCount == 0)
409  {
410  leaveAtomic();
411  return false;
412  }
413  for (int i = m_readLockCount - 1; i >= 0; --i)
414  {
415  if (m_readLocked[i] == cid)
416  {
417  for (int j = i + 1; j < m_readLockCount; ++j)
418  m_readLocked[j - 1] = m_readLocked[j];
419  --m_readLockCount;
420  break;
421  }
422  }
423  }
424  leaveAtomic();
425  return true;
426  }
427 
428  inline bool tryClaimMutex(bool write, uint32_t timeout)
429  {
431  long long timeToEnd = XsTimeStamp_now(0) + timeout;
432 
433  // write lock
434  if (write)
435  {
436  enterAtomic();
438  leaveAtomic();
439  do
440  {
441  enterAtomic();
442  bool readFail = false;
443  if (m_writeLocked == 0)
444  {
445  for (int i = 0; i < m_readLockCount; ++i)
446  {
447  if (m_readLocked[i] != cid)
448  {
449  readFail = true;
450  break;
451  }
452  }
453  }
454 
455  if (m_writeLocked != cid && (m_writeLocked != 0 || readFail))
456  {
457  leaveAtomic();
458  // wait for other locks to end
459  xsYield();
460  }
461  else
462  {
463  ++m_writeRef;
465  m_writeLocked = cid;
466  leaveAtomic();
467  return true;
468  }
469  } while (XsTimeStamp_now(0) >= timeToEnd);
470  enterAtomic();
472  leaveAtomic();
473  return false;
474  }
475  // read lock
476  // else
477  do
478  {
479  enterAtomic();
480 
481  bool readGot = false;
482  if ((m_writeLocked == 0 && m_writeLocksPending == 0) || m_writeLocked == cid)
483  readGot = true;
484  else
485  {
486  for (int i = 0; i < m_readLockCount; ++i)
487  {
488  if (m_readLocked[i] == cid)
489  {
490  readGot = true;
491  break;
492  }
493  }
494  }
495 
496  if (readGot)
497  {
498  addReadLock(cid);
499  leaveAtomic();
500  return true;
501  }
502  leaveAtomic();
503  // wait for write lock to end
504  xsYield();
505  } while (XsTimeStamp_now(0) <= timeToEnd);
506  return false;
507  }
508 
509 #ifdef XSENS_DEBUG
510 public: // these functions should only be used internally and in assert statements
511 #endif
512  inline bool haveWriteClaim() const
513  {
514  bool rv = false;
516 
517  const_cast<MutexReadWrite*>(this)->enterAtomic();
518  if (m_writeLocked == cid)
519  rv = true;
520  const_cast<MutexReadWrite*>(this)->leaveAtomic();
521  return rv;
522  }
523  // this function is only intended as a debug function for use in assert statements
524  inline bool haveReadClaim() const
525  {
526  bool rv = false;
528 
529  const_cast<MutexReadWrite*>(this)->enterAtomic();
530  if (m_writeLocked == cid)
531  rv = true;
532  else
533  {
534  for (int i = 0; i < m_readLockCount; ++i)
535  {
536  if (m_readLocked[i] == cid)
537  {
538  rv = true;
539  break;
540  }
541  }
542  }
543  const_cast<MutexReadWrite*>(this)->leaveAtomic();
544  return rv;
545  }
546 };
547 
551 {
559 };
560 
565 {
566 private:
568  volatile std::atomic_int m_writeRef;
569  volatile std::atomic<XsThreadId> m_writeLocked;
570  volatile std::atomic_int m_writeLocksPending;
571  volatile std::atomic_int m_writeLockSuspendCount;
573 
576  friend class LockSuspendable;
581 public:
582 
585  enum class Mode
586  {
587  Read,
588  Write,
590  };
591 
593  : m_writeRef(0)
594  , m_writeLocked(0)
597  , m_readLockMax(32)
598  , m_readLockCount(0)
599  {
601  }
602 
604  {
605  delete[] m_readLocked;
606  }
607 private:
608  inline void addReadLock(XsThreadId cid)
609  {
611  {
613  XsThreadId* tmp = new XsThreadId[m_readLockMax];
614  memcpy(tmp, m_readLocked, ((unsigned int)m_readLockCount)*sizeof(XsThreadId));
615  delete[] m_readLocked;
616  m_readLocked = tmp;
617  }
618  m_readLocked[m_readLockCount++] = cid;
619  }
620 
621  inline void enterAtomic()
622  {
624  }
625 
626  inline void leaveAtomic()
627  {
629  }
630 
631 protected:
632 
637  inline bool claimMutex(Mode mode)
638  {
640  // write lock
641  switch (mode)
642  {
643  case Mode::Write:
644  enterAtomic();
646  while (true)
647  {
648  bool readFail = false;
650  {
651  for (int i = 0; i < m_readLockCount; ++i)
652  {
653  if (m_readLocked[i] != cid)
654  {
655  readFail = true;
656  break;
657  }
658  }
659  }
660 
661  if ((m_writeLocked != cid && (m_writeLocked != 0 || readFail))
663  {
664  leaveAtomic();
665  xsYield(); // wait for other locks to end
666  enterAtomic();
667  }
668  else
669  {
670  ++m_writeRef;
672  m_writeLocked = cid;
673  leaveAtomic();
674  return true;
675  }
676  }
677  break;
678 
679  case Mode::Read:
680  while (true)
681  {
682  enterAtomic();
683  bool readGot = false;
684  if ((m_writeLocked == 0 && m_writeLocksPending == 0)
685  || m_writeLocked == cid
687  readGot = true;
688  else
689  {
690  for (int i = 0; i < m_readLockCount; ++i)
691  {
692  if (m_readLocked[i] == cid)
693  {
694  readGot = true;
695  break;
696  }
697  }
698  }
699 
700  if (readGot)
701  {
702  addReadLock(cid);
703  leaveAtomic();
704  return true;
705  }
706  leaveAtomic();
707  // wait for write lock to end
708  xsYield();
709  }
710  break;
711 
713  enterAtomic();
715  while (1)
716  {
717  if (m_writeLocked != cid && m_writeLocked != 0)
718  {
719  leaveAtomic();
720  xsYield(); // wait for other write locks to end
721  enterAtomic();
722  }
723  else
724  {
725  ++m_writeRef;
727  m_writeLocked = cid;
729  leaveAtomic();
730  return true;
731  }
732  }
733  break;
734 
735  default:
736  break;
737  }
738 
739  assert(0);
740  return false;
741  }
742 
748  inline bool claimMutex(bool write)
749  {
750  return claimMutex(write ? Mode::Write : Mode::Read);
751  }
752 
755  inline bool downgradeToRead(bool decreaseSuspend)
756  {
758  enterAtomic();
759  if (m_writeLocked == cid)
760  {
761  if (decreaseSuspend)
763  if (--m_writeRef == 0)
764  {
765  m_writeLocked = 0;
767  }
768  addReadLock(cid);
769  leaveAtomic();
770  return true;
771  }
772  leaveAtomic();
773  return false;
774  }
775 
778  inline bool suspendWriteLock()
779  {
781  enterAtomic();
782  if (m_writeLocked == cid)
783  {
785  leaveAtomic();
786  return true;
787  }
788  leaveAtomic();
789  return false;
790  }
791 
794  inline bool resumeWriteLock()
795  {
797  enterAtomic();
798  if (m_writeLocked == cid)
799  {
801  {
802  // wait for all read locks to end
803  while (true)
804  {
805  bool stillReading = false;
806  for (int i = 0; i < m_readLockCount; ++i)
807  {
808  if (m_readLocked[i] != cid)
809  {
810  stillReading = true;
811  break;
812  }
813  }
814 
815  if (!stillReading)
816  {
817  leaveAtomic();
818  return true;
819  }
820  leaveAtomic();
821  xsYield();
822  enterAtomic();
823  }
824  }
825  leaveAtomic();
826  return true;
827  }
828  leaveAtomic();
829  return false;
830  }
831 
837  inline bool releaseMutex(bool write, bool decreaseSuspendCount)
838  {
840  enterAtomic();
841  if (write)
842  {
843  if (m_writeLocked == cid)
844  {
845  if (decreaseSuspendCount)
847 
848  if (--m_writeRef == 0)
849  {
851  m_writeLocked = 0;
852  }
853  }
854  else
855  {
856  leaveAtomic();
857  return false;
858  }
859  }
860  else
861  {
862  if (m_readLockCount == 0)
863  {
864  leaveAtomic();
865  return false;
866  }
867  for (int i = m_readLockCount - 1; i >= 0; --i)
868  {
869  if (m_readLocked[i] == cid)
870  {
871  for (int j = i + 1; j < m_readLockCount; ++j)
872  m_readLocked[j - 1] = m_readLocked[j];
873  --m_readLockCount;
874  break;
875  }
876  }
877  }
878  leaveAtomic();
879  return true;
880  }
881 
887  inline bool releaseMutex(Mode mode, bool decreaseSuspendCount)
888  {
889  return releaseMutex(mode != Mode::Read, decreaseSuspendCount);
890  }
891 public:
892 
896  int status() const volatile
897  {
898  int rv = 0;
900  const_cast<MutexReadWriteSuspendable*>(this)->enterAtomic();
901  if (m_writeRef)
902  {
903  rv |= MSF_WriteLocked;
904  if (m_writeLocked == cid)
905  rv |= MSF_HaveWriteLock;
908  }
910  rv |= MSF_WriteLocksPending;
911  if (m_readLockCount)
912  rv |= MSF_ReadLocked;
913  for (int i = 0; i < m_readLockCount; ++i)
914  {
915  if (m_readLocked[i] == cid)
916  {
917  rv |= MSF_HaveReadLock;
918  break;
919  }
920  }
921  const_cast<MutexReadWriteSuspendable*>(this)->leaveAtomic();
922  return rv;
923  }
924 
925 #ifndef XSENS_DEBUG
926 protected:
927  // these functions should only be used internally and in assert statements
928 #endif
929 
931  inline bool haveWriteClaim() const volatile
932  {
933  return (status() & MSF_HaveWriteLock) != 0;
934  }
935 
938  inline bool haveReadClaim() const volatile
939  {
940  return (status() & (MSF_HaveWriteLock | MSF_HaveReadLock)) != 0;
941  }
942 };
943 
947 class Lock
948 {
949 private:
951  volatile std::atomic_bool m_locked;
953 
954  Lock(Lock const&) = delete;
955  Lock& operator=(Lock const&) = delete;
956  Lock(Lock&& rhs)
957  : m_mutex(rhs.m_mutex)
958  , m_locked(rhs.m_locked)
959  {
960  rhs.m_mutex = nullptr;
961  rhs.m_locked = false;
962  }
964  {
965  if (this != &rhs)
966  {
967  m_mutex = rhs.m_mutex;
968  m_locked = rhs.m_locked;
969  rhs.m_mutex = nullptr;
970  rhs.m_locked = false;
971  }
972  return *this;
973  }
974 
975 public:
976 
980  inline Lock(Mutex* mutex) : m_mutex(mutex), m_locked(false)
981  {
984  }
985 
990  inline Lock(Mutex* mutex, bool lockit) : m_mutex(mutex), m_locked(false)
991  {
992  if (lockit)
993  {
996  }
997  }
998 
1003  inline Lock(Mutex* mutex, LockState lockit) : m_mutex(mutex), m_locked(false)
1004  {
1005  if (lockit != LS_Unlocked)
1006  {
1009  }
1010  }
1011  inline ~Lock()
1012  {
1013  unlock();
1014  }
1015 
1019  inline bool lock()
1020  {
1021  if (!m_locked)
1022  {
1024  return (m_locked = m_mutex->claimMutex()) != 0;
1025  }
1026  return true;
1027  }
1028 
1032  inline bool unlock() noexcept
1033  {
1034  if (m_locked)
1035  {
1038  return !(m_locked = !m_mutex->releaseMutex());
1039  }
1040  return true;
1041  }
1042 
1047  inline bool lock(LockState ls)
1048  {
1049  if (ls == LS_Unlocked)
1050  return unlock();
1051  else
1052  return lock();
1053  }
1054 
1058  inline bool tryLock()
1059  {
1060  if (!m_locked)
1061  {
1063  return (m_locked = m_mutex->tryClaimMutex());
1064  }
1065  return true;
1066  }
1067 
1072  inline bool tryLock(LockState ls)
1073  {
1074  if (ls == LS_Unlocked)
1075  return unlock();
1076  else
1077  return tryLock();
1078  }
1079 
1081  inline bool isLocked() const
1082  {
1083  return m_locked;
1084  }
1085 };
1086 
1091 {
1092 private:
1094  volatile std::atomic_bool m_lockedR;
1095  volatile std::atomic_bool m_lockedW;
1097 
1098  LockReadWrite(LockReadWrite const&) = delete;
1099  LockReadWrite& operator=(LockReadWrite const&) = delete;
1100  LockReadWrite(LockReadWrite&&) = delete;
1101  LockReadWrite& operator=(LockReadWrite&&) = delete;
1102 public:
1103 
1106  inline LockReadWrite(MutexReadWrite* mutex, LockState lockState = LS_Unlocked) : m_mutex(mutex), m_lockedR(false), m_lockedW(false)
1107  {
1108 #if defined(XSENS_DEBUG)
1109  assert(m_mutex != NULL);
1110 #endif
1111 
1112  if (lockState == LS_Read)
1113  lock(false);
1114  else if (lockState == LS_Write)
1115  lock(true);
1116  else
1117  assert(lockState != LS_SuspendedWrite);
1118  }
1120  {
1121  unlock();
1122  }
1123 
1129  inline bool lock(bool write)
1130  {
1132  if (write)
1133  {
1134  if (m_lockedW)
1135  return true;
1136  if (m_lockedR)
1137  unlock();
1138  m_lockedW = m_mutex->claimMutex(true);
1139  assert(m_lockedW);
1140  return m_lockedW;
1141  }
1142  else
1143  {
1144  if (m_lockedW)
1145  {
1147  m_lockedW = false;
1148  assert(m_lockedR);
1149  }
1150  if (!m_lockedR)
1151  m_lockedR = m_mutex->claimMutex(false);
1152  assert(m_lockedR);
1153  return m_lockedR;
1154  }
1155  }
1156 
1161  inline bool lock(LockState ls)
1162  {
1163  assert(ls == LS_Read || ls == LS_Write);
1164  return lock(ls != LS_Read);
1165  }
1169  inline bool lockRead()
1170  {
1171  return lock(false);
1172  }
1173 
1177  inline bool lockWrite()
1178  {
1179  return lock(true);
1180  }
1181 
1185  inline bool unlock() noexcept
1186  {
1188  if (m_lockedW)
1189  {
1190  assert(!m_lockedR);
1191  m_lockedW = false;
1192  return m_mutex->releaseMutex(true);
1193  }
1194  if (m_lockedR)
1195  {
1196  m_lockedR = false;
1197  return m_mutex->releaseMutex(false);
1198  }
1199  return false;
1200  }
1201 
1207  inline bool tryLock(bool write, uint32_t timeout = 0)
1208  {
1210  if (write)
1211  {
1212  if (m_lockedW)
1213  return true;
1214  if (m_lockedR)
1215  unlock();
1216  m_lockedW = m_mutex->tryClaimMutex(true, timeout);
1217  assert(m_lockedW);
1218  return m_lockedW;
1219  }
1220  else
1221  {
1222  if (m_lockedW)
1223  {
1225  m_lockedW = false;
1226  assert(m_lockedR);
1227  }
1228  if (!m_lockedR)
1229  m_lockedR = m_mutex->tryClaimMutex(false, timeout);
1230  assert(m_lockedR);
1231  return m_lockedR;
1232  }
1233  }
1234 
1238  inline bool isLocked(bool write) const volatile
1239  {
1240  return (!write && m_lockedR) || m_lockedW;
1241  }
1242 
1246  inline bool haveWriteClaim() const volatile
1247  {
1248  return m_mutex->haveWriteClaim();
1249  }
1250 };
1251 
1260 {
1261 private:
1263  friend class LockGuarded;
1264  friend class LockSuspendable;
1265 
1266  GuardedMutex(GuardedMutex const&) = delete;
1267  GuardedMutex& operator=(GuardedMutex const&) = delete;
1268  GuardedMutex(GuardedMutex&&) = delete;
1269  GuardedMutex& operator=(GuardedMutex&&) = delete;
1270 
1271 public:
1272 
1275  inline GuardedMutex()
1276  {
1277  }
1278 
1281  inline ~GuardedMutex()
1282  {
1283  }
1284 
1287  inline bool claimMutex()
1288  {
1290  return m_guarded.claimMutex();
1291  }
1292 
1295  inline bool releaseMutex()
1296  {
1299  return true;
1300  }
1301 
1306  {
1307  return *this;
1308  }
1309 
1314  inline bool isUsing(Mutex const* mutex) const
1315  {
1316  return &m_guarded == mutex;
1317  }
1318 
1320  int status() const volatile
1321  {
1323  }
1324 
1325 #ifdef XSENS_DEBUG
1326  // this function is only intended as a debug function for use in assert statements
1327  inline bool haveGuardedLock() const
1328  {
1329  return m_guarded.haveLock();
1330  }
1331 #endif
1332 
1333 #ifndef XSENS_DEBUG
1334 protected:
1335  // these functions should only be used internally and in assert statements
1336 #endif
1339 };
1340 
1345 {
1346 private:
1348  volatile std::atomic_bool m_lockedR;
1349  volatile std::atomic_bool m_lockedW;
1350  volatile std::atomic_bool m_iSuspended; // Read: I suspended the write lock, this does not mean that it actually IS suspended
1351 
1352  LockSuspendable(LockSuspendable const&) = delete;
1353  LockSuspendable& operator=(LockSuspendable const&) = delete;
1354  LockSuspendable(LockSuspendable&&) = delete;
1356 
1357 public:
1358 
1361  inline LockSuspendable(MutexReadWriteSuspendable* mutex, LockState lockState) : m_mutex(mutex), m_lockedR(false), m_lockedW(false), m_iSuspended(false)
1362  {
1363 #if defined(XSENS_DEBUG)
1364  assert(m_mutex != NULL);
1365 #endif
1366 
1367  if (lockState != LS_Unlocked)
1368  lock(lockState);
1369  }
1370 
1373  inline LockSuspendable(GuardedMutex* mutex, LockState lockState) : m_mutex(mutex), m_lockedR(false), m_lockedW(false), m_iSuspended(false)
1374  {
1375 #if defined(XSENS_DEBUG)
1376  assert(m_mutex != NULL);
1377 #endif
1378 
1379  if (lockState != LS_Unlocked)
1380  lock(lockState);
1381  }
1382 
1384  {
1385  unlock();
1386  }
1387 
1393  inline bool lock(LockState desiredLockState)
1394  {
1395  switch (desiredLockState)
1396  {
1397  case LS_Write:
1398  if (m_lockedW)
1399  return resume();
1400  if (m_lockedR)
1401  unlock();
1403  assert(m_lockedW);
1404  return m_lockedW;
1405 
1406  case LS_SuspendedWrite:
1407  if (m_lockedW)
1408  return suspend();
1409  if (m_lockedR)
1410  unlock();
1413  assert(m_lockedW);
1414  return m_lockedW;
1415 
1416  case LS_Read:
1417  if (m_lockedW)
1418  {
1420  m_iSuspended = false;
1421  m_lockedW = false;
1422  assert(m_lockedR);
1423  }
1424  if (!m_lockedR)
1426  assert(m_lockedR);
1427  return m_lockedR;
1428 
1429  case LS_Unlocked:
1430  return unlock();
1431 
1432  default:
1433  assert(0);
1434  return false;
1435  }
1436  }
1437 
1442  inline bool lock(bool write)
1443  {
1444  return lock(write ? LS_Write : LS_Read);
1445  }
1446 
1450  inline bool lockRead()
1451  {
1452  return lock(LS_Read);
1453  }
1454 
1458  inline bool lockWrite()
1459  {
1460  return lock(LS_Write);
1461  }
1462 
1466  inline bool lockSuspendedWrite()
1467  {
1468  return lock(LS_SuspendedWrite);
1469  }
1470 
1474  inline bool suspend()
1475  {
1476  assert(m_lockedW);
1477  if (m_iSuspended)
1478  return true;
1479  m_iSuspended = true;
1480  return m_mutex->suspendWriteLock();
1481  }
1482 
1486  inline bool resume()
1487  {
1488  assert(m_lockedW);
1489  if (!m_iSuspended)
1490  return true;
1491  m_iSuspended = false;
1492  return m_mutex->resumeWriteLock();
1493  }
1494 
1497  inline bool isSuspended() const
1498  {
1499  return m_iSuspended;
1500  }
1501 
1505  inline bool mutexIsSuspended() const volatile
1506  {
1508  }
1509 
1513  inline bool unlock() noexcept
1514  {
1515  if (m_lockedW)
1516  {
1517  assert(!m_lockedR);
1518  m_lockedW = false;
1519  bool s = m_iSuspended;
1520  m_iSuspended = false;
1521  return m_mutex->releaseMutex(true, s);
1522  }
1523  if (m_lockedR)
1524  {
1525  m_lockedR = false;
1526  return m_mutex->releaseMutex(false, false);
1527  }
1528  return false;
1529  }
1530 
1534  inline bool isLocked(LockState minimumState) const
1535  {
1536  bool sus = isSuspended();
1537  if (minimumState == LS_Write)
1538  return m_lockedW && !sus;
1539  if (minimumState == LS_SuspendedWrite)
1540  return m_lockedW && sus;
1541  if (minimumState == LS_Read)
1542  return m_lockedW || m_lockedR;
1543  assert(minimumState == LS_Unlocked);
1544  return true;
1545  }
1546 
1551  bool isUsing(MutexReadWriteSuspendable const* mutex) const
1552  {
1553  return m_mutex == mutex;
1554  }
1555 
1560  bool isUsing(GuardedMutex const* mutex) const
1561  {
1562  return m_mutex == mutex;
1563  }
1564 };
1565 
1570 {
1571 private:
1573  volatile std::atomic_bool m_locked;
1574 
1575  LockGuarded(LockGuarded const&) = delete;
1576  LockGuarded& operator=(LockGuarded const&) = delete;
1577  LockGuarded(LockGuarded&&) = delete;
1578  LockGuarded& operator=(LockGuarded&&) = delete;
1579 
1580 public:
1581 
1584  inline LockGuarded(GuardedMutex* mutex, bool lockit = true) : m_mutex(mutex), m_locked(false)
1585  {
1586  if (lockit)
1588  }
1589 
1592  inline LockGuarded(GuardedMutex* mutex, LockState lockit) : m_mutex(mutex), m_locked(false)
1593  {
1594  if (lockit != LS_Unlocked)
1596  }
1597 
1600  inline ~LockGuarded()
1601  {
1602  unlock();
1603  }
1604 
1608  inline bool lock()
1609  {
1610  if (!m_locked)
1611  return (m_locked = m_mutex->claimMutex()) != 0;
1612  return true;
1613  }
1614 
1618  inline bool unlock() noexcept
1619  {
1620  if (m_locked)
1621  {
1623  return !(m_locked = !m_mutex->releaseMutex());
1624  }
1625  return true;
1626  }
1627 
1630  inline bool isLocked() const
1631  {
1632  return m_locked;
1633  }
1634 
1639  bool isUsing(GuardedMutex const* mutex) const
1640  {
1641  return m_mutex == mutex;
1642  }
1643 
1648  bool isUsing(MutexReadWriteSuspendable const* mutex) const
1649  {
1650  return m_mutex == mutex;
1651  }
1652 
1657  bool isUsing(Mutex const* mutex) const
1658  {
1659  return m_mutex->isUsing(mutex);
1660  }
1661 };
1662 
1666 template <typename K>
1668 {
1669 private:
1671 public:
1672 
1675  ProtectedValue(MutexReadWrite* mutex, bool writeLock = false)
1676  {
1677  m_lock = new LockReadWrite(mutex);
1678  m_lock->lock(writeLock);
1679  }
1680 
1684  {
1685  m_lock = pv.m_lock;
1686  m_value = pv.m_value;
1687  pv.m_lock = NULL;
1688  }
1689 
1693  {
1694  if (m_lock)
1695  delete m_lock;
1696  }
1697 
1701  void operator = (const ProtectedValue& pv)
1702  {
1703  if (&pv == this)
1704  return;
1705 
1706  assert(pv.m_lock);
1707  m_lock = pv.m_lock;
1708  m_value = pv.m_value;
1709  pv.m_lock = NULL;
1710  }
1711 
1713 };
1714 
1719 {
1720 protected:
1721 #ifdef _WIN32
1722  HANDLE* m_handleList;
1723 #else
1724  char* m_semname;
1725  sem_t* m_handle;
1726 #endif
1728 
1729  Semaphore(Semaphore const&) = delete;
1730  Semaphore& operator=(Semaphore const&) = delete;
1731  Semaphore(Semaphore&&) = delete;
1732  Semaphore& operator=(Semaphore&&) = delete;
1733 
1734 public:
1735 
1739  bool wait1();
1740 
1745  bool wait1(uint32_t timeout);
1746 
1751  int32_t post(int32_t increment = 1) noexcept;
1752 #ifdef _WIN32
1753 
1755  Semaphore(int32_t initVal = 0, uint32_t nofOtherHandles = 0, HANDLE* otherHandles = NULL);
1756 #else
1757 
1759  Semaphore(int32_t initVal = 0, uint32_t nofOtherHandles = 0, sem_t* otherHandles = NULL);
1760 #endif
1761 
1763  ~Semaphore();
1764 };
1765 
1807 {
1808  WaitCondition(WaitCondition const&) = delete;
1809  WaitCondition& operator=(WaitCondition const&) = delete;
1810  WaitCondition(WaitCondition&&) = delete;
1811  WaitCondition& operator=(WaitCondition&&) = delete;
1812 
1813 public:
1814  explicit WaitCondition(Mutex& m);
1815  ~WaitCondition();
1816 
1817  void signal();
1818  void broadcast();
1819  bool wait();
1820  bool wait(uint32_t timeout);
1821 private:
1822 #ifdef _WIN32
1823  CONDITION_VARIABLE m_cond;
1824 #else
1825  pthread_cond_t m_cond;
1826  pthread_condattr_t m_condattr;
1827 #ifdef __APPLE__
1828  int m_clockId;
1829 #else
1830  clockid_t m_clockId;
1831 #endif
1832 #endif
1834 };
1835 
1840 {
1841  WaitEvent(WaitEvent const&) = delete;
1842  WaitEvent& operator=(WaitEvent const&) = delete;
1843  WaitEvent(WaitEvent&&) = delete;
1844  WaitEvent& operator=(WaitEvent&&) = delete;
1845 
1846 public:
1847  WaitEvent();
1848  ~WaitEvent();
1849 
1850  void terminate();
1851  bool wait();
1852  void set();
1853  void reset();
1854 
1855 private:
1856 #if defined(_WIN32)
1857  HANDLE m_event;
1858 #else
1859  pthread_mutex_t m_mutex;
1860  pthread_cond_t m_cond;
1862 #endif
1863  volatile std::atomic_int m_waiterCount;
1864  volatile std::atomic_bool m_terminating;
1865 };
1866 
1873 template <typename L1, typename L2>
1874 void multiLock(L1& lock1, L2& lock2, LockState state1 = LockState::LS_Write, LockState state2 = LockState::LS_Write)
1875 {
1876  lock1.lock(state1);
1877  while (!lock2.tryLock(state2))
1878  {
1879  lock1.unlock();
1880  xsYield();
1881  lock1.lock(state1);
1882  }
1883 }
1884 
1885 } // namespace xsens
1886 
1887 #ifndef __GNUC__
1888  #pragma warning(default: 4127)
1889 #endif
1890 
1891 #endif
xsens::LockSuspendable::isUsing
bool isUsing(GuardedMutex const *mutex) const
Check if the lock is using the supplied mutex.
Definition: xsens_mutex.h:1560
xsens::LockReadWrite::operator=
LockReadWrite & operator=(LockReadWrite const &)=delete
xsens::LockReadWrite::LockReadWrite
LockReadWrite(LockReadWrite const &)=delete
xsens::LockGuarded::isUsing
bool isUsing(Mutex const *mutex) const
Check if the lock is using the supplied mutex.
Definition: xsens_mutex.h:1657
xsens::LockGuarded::isLocked
bool isLocked() const
Definition: xsens_mutex.h:1630
xsens::Semaphore::Semaphore
Semaphore(Semaphore const &)=delete
xsens::MutexReadWrite
A readers-writer mutex class.
Definition: xsens_mutex.h:248
xsens::Mutex::tryClaimMutex
bool tryClaimMutex()
Tries to claim (lock) a mutex.
Definition: xsens_mutex.h:208
XsThreadId
pthread_t XsThreadId
Definition: xsthread.h:187
xsens::LS_Write
@ LS_Write
Definition: xsens_mutex.h:127
xsens::LockSuspendable::LockSuspendable
LockSuspendable(MutexReadWriteSuspendable *mutex, LockState lockState)
Constructs a lock using a suspendable readers-writer mutex.
Definition: xsens_mutex.h:1361
xsens::LockSuspendable::LockSuspendable
LockSuspendable(GuardedMutex *mutex, LockState lockState)
Constructs a lock using a guarded mutex.
Definition: xsens_mutex.h:1373
xsens::MutexReadWrite::enterAtomic
void enterAtomic()
Definition: xsens_mutex.h:293
xsens::WaitEvent::m_cond
pthread_cond_t m_cond
Definition: xsens_mutex.h:1860
xsens::LockSuspendable::~LockSuspendable
~LockSuspendable()
Definition: xsens_mutex.h:1383
xsens::MutexReadWriteSuspendable::m_readLockMax
int m_readLockMax
Definition: xsens_mutex.h:574
xsens::LockSuspendable::m_lockedR
volatile std::atomic_bool m_lockedR
Definition: xsens_mutex.h:1348
xsens::LockSuspendable::lock
bool lock(bool write)
Convenience function that accepts the boolean write value, forwards to lock(LockState)
Definition: xsens_mutex.h:1442
xsens::WaitCondition::m_cond
pthread_cond_t m_cond
Definition: xsens_mutex.h:1825
xsens::MutexReadWriteSuspendable::m_writeLocked
volatile std::atomic< XsThreadId > m_writeLocked
Definition: xsens_mutex.h:569
xsens::WaitEvent::wait
bool wait()
Wait for the event to be set or object termination.
Definition: threading.cpp:1119
xsens::GuardedMutex::~GuardedMutex
~GuardedMutex()
Destructor.
Definition: xsens_mutex.h:1281
xsens::MutexReadWriteSuspendable::m_readLocked
XsThreadId * m_readLocked
Definition: xsens_mutex.h:572
xsens::MutexReadWriteSuspendable::releaseMutex
bool releaseMutex(bool write, bool decreaseSuspendCount)
Releases (unlocks) a mutex for read or write modes.
Definition: xsens_mutex.h:837
xsens::LockSuspendable::m_iSuspended
volatile std::atomic_bool m_iSuspended
Definition: xsens_mutex.h:1350
CHECK_LOCK_ACQUIRE
#define CHECK_LOCK_ACQUIRE()
Definition: xsens_mutex.h:118
xsens::LockSuspendable::lockWrite
bool lockWrite()
Convenience function for lock(LS_Write);.
Definition: xsens_mutex.h:1458
xsens::GuardedMutex::operator=
GuardedMutex & operator=(GuardedMutex const &)=delete
xsens::MutexReadWrite::m_access
Mutex m_access
Definition: xsens_mutex.h:251
xsens::Lock::m_mutex
Mutex * m_mutex
Definition: xsens_mutex.h:950
xsens::MutexReadWriteSuspendable
A readers-writer mutex class that is able to be suspended.
Definition: xsens_mutex.h:564
xsens::LockSuspendable::operator=
LockSuspendable & operator=(LockSuspendable const &)=delete
xsens::WaitEvent::terminate
void terminate()
Terminates the thread.
Definition: threading.cpp:1162
s
XmlRpcServer s
xsens::LockGuarded::isUsing
bool isUsing(MutexReadWriteSuspendable const *mutex) const
Check if the lock is using the supplied mutex.
Definition: xsens_mutex.h:1648
xsens::LockReadWrite::lock
bool lock(bool write)
Make sure that the lock has exactly the given lock state.
Definition: xsens_mutex.h:1129
xsens::WaitEvent::WaitEvent
WaitEvent()
Definition: threading.cpp:1100
xsens::Mutex::isLocked
bool isLocked() const volatile
Definition: xsens_mutex.h:233
xsens::Semaphore::m_semname
char * m_semname
A name of the semaphore.
Definition: xsens_mutex.h:1724
xsens::MutexReadWrite::haveWriteClaim
bool haveWriteClaim() const
Definition: xsens_mutex.h:512
xsens::MutexReadWrite::m_writeRef
volatile std::atomic_int m_writeRef
Definition: xsens_mutex.h:252
xsens::ProtectedValue::ProtectedValue
ProtectedValue(const ProtectedValue &pv)
Constructs a protected value using a reference of another protected value.
Definition: xsens_mutex.h:1683
xsens::WaitEvent::set
void set()
Set the event.
Definition: threading.cpp:1136
xsens::LockSuspendable::isLocked
bool isLocked(LockState minimumState) const
Definition: xsens_mutex.h:1534
xstimestamp.h
xsens::WaitCondition::~WaitCondition
~WaitCondition()
Destroy the wait condition.
Definition: threading.cpp:951
xsens::MutexReadWriteSuspendable::~MutexReadWriteSuspendable
~MutexReadWriteSuspendable()
Definition: xsens_mutex.h:603
xsens::LockReadWrite::haveWriteClaim
bool haveWriteClaim() const volatile
Definition: xsens_mutex.h:1246
xsens::LockSuspendable::m_mutex
MutexReadWriteSuspendable * m_mutex
Definition: xsens_mutex.h:1347
xsens::MutexReadWriteSuspendable::haveReadClaim
bool haveReadClaim() const volatile
Definition: xsens_mutex.h:938
xsens::LockReadWrite::isLocked
bool isLocked(bool write) const volatile
Definition: xsens_mutex.h:1238
xsens::Lock::lock
bool lock()
Locks the unlocked mutex.
Definition: xsens_mutex.h:1019
xsens::LockReadWrite
A readers-writer lock class.
Definition: xsens_mutex.h:1090
xsthread.h
xsens::LockReadWrite::CHECK_LOCK_DEFINE
CHECK_LOCK_DEFINE()
xsens::Mutex::operator=
Mutex & operator=(Mutex const &)=delete
CHECK_LOCK_RELEASE
#define CHECK_LOCK_RELEASE()
Definition: xsens_mutex.h:119
xsens::WaitCondition::m_clockId
clockid_t m_clockId
Definition: xsens_mutex.h:1830
xsens::Lock::isLocked
bool isLocked() const
Definition: xsens_mutex.h:1081
xsens::WaitCondition::operator=
WaitCondition & operator=(WaitCondition const &)=delete
xsens::LockReadWrite::lockWrite
bool lockWrite()
Convenience function for lock(true);.
Definition: xsens_mutex.h:1177
xsens::LockGuarded::LockGuarded
LockGuarded(GuardedMutex *mutex, LockState lockit)
Constructs a guarded lock using a guarded mutex and a lock state.
Definition: xsens_mutex.h:1592
xsens::MutexReadWrite::MutexReadWrite
MutexReadWrite()
Definition: xsens_mutex.h:266
xsYield
#define xsYield()
Release the remainder of the timeslice so other operations can run.
Definition: xsthread.h:182
xsens::Lock::operator=
Lock & operator=(Lock &&rhs)
Definition: xsens_mutex.h:963
xsens::LockReadWrite::tryLock
bool tryLock(bool write, uint32_t timeout=0)
Tries to lock the write/read unlocked mutex before a given time runs out.
Definition: xsens_mutex.h:1207
xsens::LockSuspendable::lock
bool lock(LockState desiredLockState)
Make sure that the lock has exactly the given lock state.
Definition: xsens_mutex.h:1393
xsens::Mutex::releaseMutex
bool releaseMutex()
Releases (unlocks) a mutex.
Definition: xsens_mutex.h:193
xsens::MutexReadWriteSuspendable::claimMutex
bool claimMutex(Mode mode)
Claims (locks) a mutex using a given mode.
Definition: xsens_mutex.h:637
xsens::MutexStatusFlags
MutexStatusFlags
An enum that hold mutex status flags.
Definition: xsens_mutex.h:550
xsens::GuardedMutex::suspendable
MutexReadWriteSuspendable & suspendable()
Definition: xsens_mutex.h:1305
xsens::Lock::tryLock
bool tryLock(LockState ls)
Tries to lock the unlocked mutex.
Definition: xsens_mutex.h:1072
xsens::LS_SuspendedWrite
@ LS_SuspendedWrite
Definition: xsens_mutex.h:127
xsens::LockGuarded::operator=
LockGuarded & operator=(LockGuarded const &)=delete
xsens::Lock::Lock
Lock(Mutex *mutex)
Constructs a lock a given mutex.
Definition: xsens_mutex.h:980
xsens::MutexReadWriteSuspendable::m_writeLocksPending
volatile std::atomic_int m_writeLocksPending
Definition: xsens_mutex.h:570
xsens::Lock::Lock
Lock(Lock &&rhs)
Definition: xsens_mutex.h:956
xsens::WaitCondition::broadcast
void broadcast()
Unblock all waiting threads.
Definition: threading.cpp:977
xsens::MutexReadWrite::haveReadClaim
bool haveReadClaim() const
Definition: xsens_mutex.h:524
xsens::MutexReadWriteSuspendable::m_writeLockSuspendCount
volatile std::atomic_int m_writeLockSuspendCount
Definition: xsens_mutex.h:571
xsens::Semaphore::m_handle
sem_t * m_handle
A semaphore's handle.
Definition: xsens_mutex.h:1725
xsens::ProtectedValue::operator=
void operator=(const ProtectedValue &pv)
Assignment operator, copies contents from the pv protected value.
Definition: xsens_mutex.h:1701
xsens::MutexReadWriteSuspendable::Mode
Mode
An enum class that holds a three different modes of a suspendable mutex.
Definition: xsens_mutex.h:585
xsens::LockReadWrite::m_mutex
MutexReadWrite * m_mutex
Definition: xsens_mutex.h:1093
xsens::WaitCondition::WaitCondition
WaitCondition(WaitCondition const &)=delete
xsens::LockGuarded::LockGuarded
LockGuarded(LockGuarded const &)=delete
xsens::MSF_HaveReadLock
@ MSF_HaveReadLock
Definition: xsens_mutex.h:552
xsens::Lock::lock
bool lock(LockState ls)
Locks the unlocked mutex.
Definition: xsens_mutex.h:1047
xsens::MSF_WriteLocked
@ MSF_WriteLocked
Definition: xsens_mutex.h:555
xsens::Lock::Lock
Lock(Mutex *mutex, LockState lockit)
Constructs a lock a given mutex.
Definition: xsens_mutex.h:1003
xsens::ProtectedValue::~ProtectedValue
~ProtectedValue()
Destructor.
Definition: xsens_mutex.h:1692
xsens::LockReadWrite::m_lockedW
volatile std::atomic_bool m_lockedW
Definition: xsens_mutex.h:1095
xsens::Mutex::m_mutex
CRITICAL_SECTION m_mutex
Definition: xsens_mutex.h:136
xsens::MutexReadWriteSuspendable::Mode::SuspendedWrite
@ SuspendedWrite
xsens::Semaphore
A semaphore class.
Definition: xsens_mutex.h:1718
xsens::MutexReadWrite::leaveAtomic
void leaveAtomic()
Definition: xsens_mutex.h:298
xsens::MutexReadWriteSuspendable::Mode::Write
@ Write
uint32_t
unsigned int uint32_t
Definition: pstdint.h:485
xsens::LockGuarded::~LockGuarded
~LockGuarded()
Destructor.
Definition: xsens_mutex.h:1600
xsens::WaitCondition::wait
bool wait()
Wait until we're signalled to continue.
Definition: threading.cpp:994
xsens::MutexReadWriteSuspendable::resumeWriteLock
bool resumeWriteLock()
Resumes an existing write lock so read locks are no longer allowed.
Definition: xsens_mutex.h:794
xsens::LockSuspendable::lockRead
bool lockRead()
Convenience function for lock(LS_Read);.
Definition: xsens_mutex.h:1450
xsens::LockReadWrite::lockRead
bool lockRead()
Convenience function for lock(false);.
Definition: xsens_mutex.h:1169
xsens::LockSuspendable::suspend
bool suspend()
Suspend a write lock, allowing readers access, but preventing others from getting a write lock.
Definition: xsens_mutex.h:1474
xsens::WaitEvent
An event that can be set/reset and that can be waited for.
Definition: xsens_mutex.h:1839
xsens::MutexReadWrite::tryClaimMutex
bool tryClaimMutex(bool write, uint32_t timeout)
Definition: xsens_mutex.h:428
xsens::MutexReadWriteSuspendable::m_writeRef
volatile std::atomic_int m_writeRef
Definition: xsens_mutex.h:568
xsens::LockSuspendable::LockSuspendable
LockSuspendable(LockSuspendable const &)=delete
xsens::WaitEvent::~WaitEvent
~WaitEvent()
Definition: threading.cpp:1109
xsens::Lock::m_locked
volatile std::atomic_bool m_locked
Definition: xsens_mutex.h:951
xsens::WaitCondition::signal
void signal()
Unblock a single waiting thread.
Definition: threading.cpp:967
xsens::LockReadWrite::~LockReadWrite
~LockReadWrite()
Definition: xsens_mutex.h:1119
xsens::LockSuspendable::mutexIsSuspended
bool mutexIsSuspended() const volatile
Definition: xsens_mutex.h:1505
xsens::Mutex
A base mutex class.
Definition: xsens_mutex.h:132
xsens::MutexReadWriteSuspendable::operator=
MutexReadWriteSuspendable & operator=(MutexReadWriteSuspendable const &)=delete
xsens::WaitEvent::m_terminating
volatile std::atomic_bool m_terminating
Definition: xsens_mutex.h:1864
xsens::LS_Read
@ LS_Read
Definition: xsens_mutex.h:127
xsens::WaitEvent::m_waiterCount
volatile std::atomic_int m_waiterCount
Definition: xsens_mutex.h:1863
xsens::WaitEvent::m_mutex
pthread_mutex_t m_mutex
Definition: xsens_mutex.h:1859
xsens::MutexReadWriteSuspendable::m_readLockCount
int m_readLockCount
Definition: xsens_mutex.h:575
xsens::LS_Unlocked
@ LS_Unlocked
Definition: xsens_mutex.h:127
xsens::Mutex::~Mutex
~Mutex()
Definition: xsens_mutex.h:159
xsens::LockSuspendable::isSuspended
bool isSuspended() const
Definition: xsens_mutex.h:1497
xsens::MutexReadWrite::operator=
MutexReadWrite & operator=(MutexReadWrite const &)=delete
xsens::LockReadWrite::unlock
bool unlock() noexcept
Unlocks the write or read locked mutex.
Definition: xsens_mutex.h:1185
xsens::Lock::Lock
Lock(Lock const &)=delete
xsens::LockGuarded::m_mutex
GuardedMutex * m_mutex
Definition: xsens_mutex.h:1572
xsens::Mutex::m_lockCount
volatile std::atomic_int m_lockCount
Definition: xsens_mutex.h:142
xsens::multiLock
void multiLock(L1 &lock1, L2 &lock2, LockState state1=LockState::LS_Write, LockState state2=LockState::LS_Write)
Lock two mutex-locks in the order in which they appear, rolling back the locks if one fails....
Definition: xsens_mutex.h:1874
xsens::MutexReadWrite::claimMutex
bool claimMutex(bool write)
Definition: xsens_mutex.h:303
xsens::ProtectedValue::m_value
K m_value
A type name of this class.
Definition: xsens_mutex.h:1712
xsens::LockReadWrite::m_lockedR
volatile std::atomic_bool m_lockedR
Definition: xsens_mutex.h:1094
xsens::WaitEvent::m_triggered
bool m_triggered
Definition: xsens_mutex.h:1861
xsens::MutexReadWriteSuspendable::status
int status() const volatile
Definition: xsens_mutex.h:896
XsTimeStamp_now
XSTYPES_DLL_API int64_t XsTimeStamp_now(struct XsTimeStamp *thisPtr)
xsens::WaitCondition::m_condattr
pthread_condattr_t m_condattr
Definition: xsens_mutex.h:1826
start
ROSCPP_DECL void start()
xsens::LockSuspendable::m_lockedW
volatile std::atomic_bool m_lockedW
Definition: xsens_mutex.h:1349
xsens::MutexReadWriteSuspendable::downgradeToRead
bool downgradeToRead(bool decreaseSuspend)
Downgrade an existing write lock to a read lock.
Definition: xsens_mutex.h:755
xsens::MutexReadWriteSuspendable::m_access
Mutex m_access
Definition: xsens_mutex.h:567
xsens::MSF_GuardedLocked
@ MSF_GuardedLocked
Definition: xsens_mutex.h:558
xsens::Lock::unlock
bool unlock() noexcept
Unlocks the locked mutex.
Definition: xsens_mutex.h:1032
xsens::ProtectedValue::m_lock
LockReadWrite * m_lock
Definition: xsens_mutex.h:1670
xsens::Semaphore::~Semaphore
~Semaphore()
Destructor.
Definition: threading.cpp:834
xsens::Mutex::m_lockedBy
XsThreadId m_lockedBy
Definition: xsens_mutex.h:141
xsens::MutexReadWriteSuspendable::addReadLock
void addReadLock(XsThreadId cid)
Definition: xsens_mutex.h:608
xsens::MutexReadWrite::m_writeLocksPending
volatile std::atomic_int m_writeLocksPending
Definition: xsens_mutex.h:254
xsens::LockGuarded::isUsing
bool isUsing(GuardedMutex const *mutex) const
Check if the lock is using the supplied mutex.
Definition: xsens_mutex.h:1639
xsens::MutexReadWrite::addReadLock
void addReadLock(XsThreadId cid)
Definition: xsens_mutex.h:280
xsens::MutexReadWrite::releaseMutex
bool releaseMutex(bool write)
Definition: xsens_mutex.h:389
xsens::LockSuspendable::resume
bool resume()
Resume a write lock.
Definition: xsens_mutex.h:1486
xsens::Semaphore::m_nofHandles
uint32_t m_nofHandles
A number of the semaphore's handles.
Definition: xsens_mutex.h:1727
xsens::MutexReadWriteSuspendable::haveWriteClaim
bool haveWriteClaim() const volatile
Definition: xsens_mutex.h:931
xsens::LockState
LockState
Definition: xsens_mutex.h:127
xsens::Mutex::claimMutex
bool claimMutex()
Claims (locks) a mutex.
Definition: xsens_mutex.h:178
xsens::LockGuarded::unlock
bool unlock() noexcept
Unlocks the locked mutex.
Definition: xsens_mutex.h:1618
xsens::Lock
A base class for a Lock.
Definition: xsens_mutex.h:947
xsens::ProtectedValue
A protected value class.
Definition: xsens_mutex.h:1667
xsens::LockGuarded::lock
bool lock()
Locks the unlocked mutex.
Definition: xsens_mutex.h:1608
xsens::LockGuarded::LockGuarded
LockGuarded(GuardedMutex *mutex, bool lockit=true)
Constructs a guarded lock using a guarded mutex.
Definition: xsens_mutex.h:1584
xsens::MutexReadWrite::downgradeToRead
bool downgradeToRead()
Downgrade an existing write lock to a read lock.
Definition: xsens_mutex.h:373
int32_t
signed int int32_t
Definition: pstdint.h:515
xsens::Lock::~Lock
~Lock()
Definition: xsens_mutex.h:1011
xsens::Mutex::Mutex
Mutex()
Definition: xsens_mutex.h:146
xsens::GuardedMutex::claimMutex
bool claimMutex()
Definition: xsens_mutex.h:1287
xsens::MSF_WriteLockSuspended
@ MSF_WriteLockSuspended
Definition: xsens_mutex.h:554
xsens::WaitEvent::operator=
WaitEvent & operator=(WaitEvent const &)=delete
xsens::LockGuarded::m_locked
volatile std::atomic_bool m_locked
Definition: xsens_mutex.h:1573
xsens::LockReadWrite::lock
bool lock(LockState ls)
Convenience function that accepts the generic LockState, forwards to lock(bool)
Definition: xsens_mutex.h:1161
xsens::WaitCondition
A platform independent wait condition implementation.
Definition: xsens_mutex.h:1806
xsens::LockSuspendable::unlock
bool unlock() noexcept
Unlocks the write or read locked mutex.
Definition: xsens_mutex.h:1513
xsens::WaitCondition::m_mutex
Mutex & m_mutex
Definition: xsens_mutex.h:1833
xsens::LockReadWrite::LockReadWrite
LockReadWrite(MutexReadWrite *mutex, LockState lockState=LS_Unlocked)
Consturctor.
Definition: xsens_mutex.h:1106
xsens::LockSuspendable::lockSuspendedWrite
bool lockSuspendedWrite()
Convenience function for lock(LS_SuspendedWrite);.
Definition: xsens_mutex.h:1466
XSENS_MSC_WARNING_SUPPRESS
#define XSENS_MSC_WARNING_SUPPRESS(...)
Definition: xstypesconfig.h:89
xsens::LockSuspendable
A readers-writer lock class that is able to be suspended.
Definition: xsens_mutex.h:1344
xsens::GuardedMutex
A two-layer mutex, typically used for status+data protection.
Definition: xsens_mutex.h:1259
xsens::MutexReadWrite::m_readLockCount
int m_readLockCount
Definition: xsens_mutex.h:258
xsens::LockSuspendable::isUsing
bool isUsing(MutexReadWriteSuspendable const *mutex) const
Check if the lock is using the supplied mutex.
Definition: xsens_mutex.h:1551
xsens::WaitEvent::reset
void reset()
Reset the event.
Definition: threading.cpp:1148
xsens::MutexReadWrite::~MutexReadWrite
~MutexReadWrite()
Definition: xsens_mutex.h:275
xsens::MutexReadWrite::m_writeLocked
volatile std::atomic< XsThreadId > m_writeLocked
Definition: xsens_mutex.h:253
xsens::MutexReadWrite::m_readLockMax
int m_readLockMax
Definition: xsens_mutex.h:257
xsens::MSF_ReadLocked
@ MSF_ReadLocked
Definition: xsens_mutex.h:556
xsGetCurrentThreadId
#define xsGetCurrentThreadId()
Definition: xsthread.h:191
xsens::Lock::tryLock
bool tryLock()
Tries to lock the unlocked mutex.
Definition: xsens_mutex.h:1058
xsens::Semaphore::operator=
Semaphore & operator=(Semaphore const &)=delete
xsens::GuardedMutex::isUsing
bool isUsing(Mutex const *mutex) const
Check if the guarded mutex is equal to the supplied mutex.
Definition: xsens_mutex.h:1314
xsens::Semaphore::post
int32_t post(int32_t increment=1) noexcept
Increases the count of the specified semaphore object by a specified amount.
Definition: threading.cpp:882
xsens::MutexReadWriteSuspendable::MutexReadWriteSuspendable
MutexReadWriteSuspendable()
Definition: xsens_mutex.h:592
xsens::MutexReadWriteSuspendable::claimMutex
bool claimMutex(bool write)
Claims (locks) a mutex for read or write modes.
Definition: xsens_mutex.h:748
xsens::GuardedMutex::status
int status() const volatile
Definition: xsens_mutex.h:1320
xsens::Semaphore::wait1
bool wait1()
Waits for an infinite time or until the semaphore is released.
Definition: threading.cpp:841
xsens::Lock::Lock
Lock(Mutex *mutex, bool lockit)
Constructs a lock a given mutex.
Definition: xsens_mutex.h:990
xsens
Definition: threading.cpp:78
xsens::Lock::operator=
Lock & operator=(Lock const &)=delete
xsens::MSF_WriteLocksPending
@ MSF_WriteLocksPending
Definition: xsens_mutex.h:557
xsens::GuardedMutex::releaseMutex
bool releaseMutex()
Definition: xsens_mutex.h:1295
xsens::MutexReadWrite::m_readLocked
XsThreadId * m_readLocked
Definition: xsens_mutex.h:255
xsens::MutexReadWriteSuspendable::enterAtomic
void enterAtomic()
Definition: xsens_mutex.h:621
xsens::Lock::CHECK_LOCK_DEFINE
CHECK_LOCK_DEFINE()
xsens::MutexReadWriteSuspendable::releaseMutex
bool releaseMutex(Mode mode, bool decreaseSuspendCount)
Releases (unlocks) a mutex using a given mode.
Definition: xsens_mutex.h:887
xsens::MutexReadWriteSuspendable::leaveAtomic
void leaveAtomic()
Definition: xsens_mutex.h:626
XsTimeStamp
This class contains method to set, retrieve and compare timestamps.
Definition: xstimestamp.h:115
xsens::ProtectedValue::ProtectedValue
ProtectedValue(MutexReadWrite *mutex, bool writeLock=false)
Constructs a protected value using a readers-writer mutex.
Definition: xsens_mutex.h:1675
xsens::GuardedMutex::m_guarded
Mutex m_guarded
Definition: xsens_mutex.h:1262
xsens::LockGuarded
A guarded lock class.
Definition: xsens_mutex.h:1569
xsens::GuardedMutex::GuardedMutex
GuardedMutex()
Constructor.
Definition: xsens_mutex.h:1275
xsens::MutexReadWriteSuspendable::Mode::Read
@ Read
xsens::MutexReadWriteSuspendable::suspendWriteLock
bool suspendWriteLock()
Suspend an existing write lock so read locks are allowed, but do not allow other write locks.
Definition: xsens_mutex.h:778
xsens::MSF_HaveWriteLock
@ MSF_HaveWriteLock
Definition: xsens_mutex.h:553


xsens_mti_driver
Author(s):
autogenerated on Sun Sep 3 2023 02:43:20