NCBI C++ ToolKit
ncbimtx.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef CORELIB___NCBIMTX__HPP
2 #define CORELIB___NCBIMTX__HPP
3 
4 /* $Id: ncbimtx.hpp 99661 2023-04-27 17:38:45Z vasilche $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Author: Denis Vakatov, Aleksey Grichenko, Andrei Gourianov
30  *
31  *
32  */
33 
34 /// @file ncbimtx.hpp
35 /// Multi-threading -- mutexes; rw-locks; semaphore
36 ///
37 /// MUTEX:
38 ///
39 /// MUTEX CLASSES:
40 /// - SSystemFastMutex -- platform-dependent mutex functionality
41 /// - SSystemMutex -- platform-dependent mutex functionality
42 /// - CFastMutex -- simple mutex with fast lock/unlock functions
43 /// - CMutex -- mutex that allows nesting (with runtime checks)
44 /// - CFastMutexGuard -- acquire fast mutex, then guarantee for its release
45 /// - CMutexGuard -- acquire mutex, then guarantee for its release
46 ///
47 /// RW-LOCK:
48 /// - CInternalRWLock -- platform-dependent RW-lock structure (fwd-decl)
49 /// - CRWLock -- Read/Write lock related data and methods
50 /// - CAutoRW -- guarantee RW-lock release
51 /// - CReadLockGuard -- acquire R-lock, then guarantee for its release
52 /// - CWriteLockGuard -- acquire W-lock, then guarantee for its release
53 ///
54 /// CONDITION VARIABLE:
55 /// - CConditionVariable -- condition variable
56 ///
57 /// SEMAPHORE:
58 /// - CSemaphore -- application-wide semaphore
59 ///
60 
61 
62 #include <corelib/ncbithr_conf.hpp>
63 #include <corelib/guard.hpp>
64 #include <corelib/ncbiobj.hpp>
65 #include <corelib/ncbitime.hpp>
66 #include <memory>
67 #include <deque>
68 #ifdef NCBI_COMPILER_MSVC
69 # include <intrin.h>
70 # pragma intrinsic(_ReadWriteBarrier)
71 #endif
72 
73 #if defined(NCBI_WIN32_THREADS)
74 #define NCBI_SRWLOCK_USE_NEW 1
75 #define NCBI_SEMAPHORE_USE_NEW 1
76 #endif
77 
78 #if NCBI_SRWLOCK_USE_NEW || NCBI_SEMAPHORE_USE_NEW
79 # include <atomic>
80 # include <mutex>
81 # include <condition_variable>
82 #endif
83 
84 
85 /** @addtogroup Threads
86  *
87  * @{
88  */
89 
90 
91 #if defined(_DEBUG)
92 /// Mutex debug setting.
93 # define INTERNAL_MUTEX_DEBUG
94 #else
95 # undef INTERNAL_MUTEX_DEBUG
96 /// Mutex debug setting.
97 # define INTERNAL_MUTEX_DEBUG
98 #endif
99 
100 
102 
103 /////////////////////////////////////////////////////////////////////////////
104 //
105 // DECLARATIONS of internal (platform-dependent) representations
106 //
107 // TMutex -- internal mutex type
108 //
109 
110 #if defined(NCBI_NO_THREADS)
111 
112 /// Define a platform independent system mutex.
113 typedef int TSystemMutex; // fake
114 # define SYSTEM_MUTEX_INITIALIZER 0
115 
116 #elif defined(NCBI_POSIX_THREADS)
117 
118 /// Define a platform independent system mutex.
119 typedef pthread_mutex_t TSystemMutex;
120 # define SYSTEM_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
121 
122 #elif defined(NCBI_WIN32_THREADS)
123 
124 # define NCBI_USE_CRITICAL_SECTION
125 # define NCBI_FASTMUTEX_USE_NEW
126 # define NCBI_FASTRWLOCK_USE_NEW
127 
128 # if defined(NCBI_FASTMUTEX_USE_NEW)
129 typedef SRWLOCK TSystemMutex;
130 /// Define a platform independent system mutex.
131 # elif defined(NCBI_USE_CRITICAL_SECTION)
132 typedef CRITICAL_SECTION TSystemMutex;
133 # else
134 typedef HANDLE TSystemMutex;
135 # endif
136 
137 # undef SYSTEM_MUTEX_INITIALIZER
138 
139 #else
140 # error "Unknown threading model."
141 #endif
142 
143 
144 #if defined(NCBI_NO_THREADS)
145 #define NCBI_NAMESPACE_MUTEX ncbi_namespace_mutex_st
146 #else
147 #define NCBI_NAMESPACE_MUTEX ncbi_namespace_mutex_mt
148 #endif
149 
150 
151 /// Get the current thread ID.
153 {
154 #if defined(NCBI_NO_THREADS)
155  return TThreadSystemID(0);
156 #elif defined(NCBI_POSIX_THREADS)
157  return pthread_self();
158 #elif defined(NCBI_WIN32_THREADS)
159  return GetCurrentThreadId();
160 #endif
161 }
162 
163 /// Use in defining initial value of system mutex.
164 #define THREAD_SYSTEM_ID_INITIALIZER 0
165 
166 
167 /////////////////////////////////////////////////////////////////////////////
168 ///
169 /// CThreadSystemID --
170 ///
171 /// Define thread system ID.
172 ///
173 /// The CThreadSystemID is based on the platform dependent thread ID type,
174 /// TThreadSystemID, defined in ncbithr_conf.hpp.
175 
177 {
178 public:
179  /// Define a simpler alias for TThreadSystemID.
181 
182  TID m_ID; ///< Thread ID.
183 
184  /// Get the current thread ID.
186  {
187  CThreadSystemID tid;
189  return tid;
190  }
191 
192  /// Equality operator for thread ID.
193  bool operator==(const CThreadSystemID& tid) const
194  {
195  return m_ID == tid.m_ID;
196  }
197 
198  /// Non-equality operator for thread ID.
199  bool operator!=(const CThreadSystemID& tid) const
200  {
201  return m_ID != tid.m_ID;
202  }
203 
204  /// volatile versions of above methods
205  void Set(const CThreadSystemID& tid) volatile
206  {
207  m_ID = tid.m_ID;
208  }
209  bool Is(const CThreadSystemID& tid) const volatile
210  {
211  return m_ID == tid.m_ID;
212  }
213  bool IsNot(const CThreadSystemID& tid) const volatile
214  {
215  return m_ID != tid.m_ID;
216  }
217 };
218 
219 
220 /////////////////////////////////////////////////////////////////////////////
221 ///
222 /// CMutexException --
223 ///
224 /// Define exceptions generated by mutexes.
225 ///
226 /// CMutexException inherits its basic functionality from CCoreException
227 /// and defines additional error codes for applications.
228 
230 {
231 public:
232  /// Error types that a mutex can generate.
233  enum EErrCode {
234  eLock, ///< Lock error
235  eUnlock, ///< Unlock error
236  eTryLock, ///< Attempted lock error
237  eOwner, ///< Not owned error
238  eUninitialized ///< Uninitialized error
239  };
240 
241  /// Translate from the error code value to its string representation.
242  virtual const char* GetErrCodeString(void) const override;
243 
244  // Standard exception boilerplate code.
246 };
247 
248 /////////////////////////////////////////////////////////////////////////////
249 //
250 // SYSTEM MUTEX
251 //
252 // SSystemFastMutex
253 // SSystemMutex
254 //
255 
256 class CFastMutex;
257 class CAutoInitializeStaticMutex;
258 class CMutex;
259 class CAutoInitializeStaticFastMutex;
260 class CFastMutex;
261 class CSafeStaticPtr_Base;
262 
263 
264 /////////////////////////////////////////////////////////////////////////////
265 ///
266 /// SSystemFastMutex --
267 ///
268 /// Define system fast mutex.
269 ///
270 /// Internal platform-dependent fast mutex implementation to be used by CMutex
271 /// and CFastMutex only.
272 
274 
276 {
277  TSystemMutex m_Handle; ///< Mutex handle
278 
279  /// Initialization flag values.
280  enum EMagic {
281  eMutexUninitialized = 0, ///< Uninitialized value.
282  eMutexInitialized = 0x2487adab ///< Magic initialized value,
283  };
284  volatile EMagic m_Magic; ///< Magic flag
285 
286  /// This is for condition variables
288  {
289  eNormal, /// Modify object data and call system
290  ePseudo /// Modify object data, but do not call system
291  };
292 
293  /// Acquire mutex for the current thread with no nesting checks.
295  void Lock(ELockSemantics lock = eNormal);
296 
297  /// Release mutex with no owner or nesting checks.
299  void Unlock(ELockSemantics lock = eNormal);
300 
301  /// Try to lock.
302  ///
303  /// @return
304  /// TRUE on success; FALSE, otherwise.
306  bool TryLock(void);
307 
308  /// Check initialized value of mutex.
309  void CheckInitialized(void) const;
310 
311  // Methods for throwing exceptions, to make inlined methods lighter
312 
313  /// Throw uninitialized ("eUninitialized") exception.
314  NCBI_NORETURN NCBI_XNCBI_EXPORT
315  static void ThrowUninitialized(void);
316 
317  /// Throw lock failed("eLocked") exception.
318  NCBI_NORETURN NCBI_XNCBI_EXPORT
319  static void ThrowLockFailed(void);
320 
321  /// Throw unlock failed("eUnlocked") exception.
322  NCBI_NORETURN NCBI_XNCBI_EXPORT
323  static void ThrowUnlockFailed(void);
324 
325  /// Throw try lock failed("eTryLock") exception.
326  NCBI_NORETURN NCBI_XNCBI_EXPORT
327  static void ThrowTryLockFailed(void);
328 
329 #if !defined(NCBI_OS_MSWIN)
330  // MS VC 6 treats classes with any non-public member as non-POD.
331 protected:
332 #endif
333 
334  /// Check if mutex is initialized.
335  ///
336  /// @return
337  /// TRUE if initialized; FALSE, otherwise.
338  bool IsInitialized(void) const;
339 
340  /// Check if mutex is un-initialized.
341  ///
342  /// @return
343  /// TRUE if un-initialized; FALSE, otherwise.
344  bool IsUninitialized(void) const;
345 
346  /// Initialize static mutex.
347  ///
348  /// Must be called only once.
350  void InitializeStatic(void);
351 
352  /// Initialize dynamic mutex.
353  ///
354  /// Initialize mutex if it located in heap or stack. This must be called
355  /// only once. Do not count on zeroed memory values for initializing
356  /// mutex values.
358  void InitializeDynamic(void);
359 
360  /// Destroy mutex.
362  void Destroy(void);
363 
364  /// Initialize mutex handle.
365  ///
366  /// Must be called only once.
368  void InitializeHandle(void);
369 
370  /// Destroy mutex handle.
371  ///
372  /// Must be called only once.
374  void DestroyHandle(void);
375 
376  friend struct SSystemMutex;
377  friend class ::ncbi::CAutoInitializeStaticFastMutex;
378  friend class ::ncbi::CFastMutex;
379  friend class ::ncbi::CSafeStaticPtr_Base;
380 };
381 
382 } // NCBI_NAMESPACE_MUTEX
383 
384 using NCBI_NAMESPACE_MUTEX::SSystemFastMutex;
385 
386 
387 /// typedefs for ease of use
389 
390 /// ...and backward compatibility
392 
393 
394 class CMutex;
395 
396 
397 
398 /////////////////////////////////////////////////////////////////////////////
399 ///
400 /// SSystemMutex --
401 ///
402 /// Define system mutex.
403 ///
404 /// Internal platform-dependent mutex implementation to be used by CMutex
405 /// and CFastMutex only.
406 
407 namespace NCBI_NAMESPACE_MUTEX {
408 
410 {
411  SSystemFastMutex m_Mutex; ///< Mutex value
412 
413  atomic<TThreadSystemID> m_Owner; ///< Platform-dependent owner thread ID
414 
415  atomic<int> m_Count; ///< # of recursive (in the same thread) locks
416 
417  /// Acquire mutex for the current thread.
419  void Lock
420  (SSystemFastMutex::ELockSemantics lock = SSystemFastMutex::eNormal);
421 
422  /// Release mutex.
424  void Unlock
425  (SSystemFastMutex::ELockSemantics lock = SSystemFastMutex::eNormal);
426 
427  /// Try to lock.
428  ///
429  /// @return
430  /// TRUE on success; FALSE, otherwise.
432  bool TryLock(void);
433 
434  // Methods for throwing exceptions, to make inlined methods lighter
435  // throw exception eOwner
436 
437  /// Throw not owned("eOwner") exception.
438  NCBI_NORETURN NCBI_XNCBI_EXPORT
439  static void ThrowNotOwned(void);
440 
441 #if !defined(NCBI_OS_MSWIN)
442 protected:
443 #endif
444  /// Check if mutex is initialized.
445  ///
446  /// @return
447  /// TRUE if initialized; FALSE, otherwise.
448  bool IsInitialized(void) const;
449 
450  /// Check if mutex is un-initialized.
451  ///
452  /// @return
453  /// TRUE if un-initialized; FALSE, otherwise.
454  bool IsUninitialized(void) const;
455 
456  /// Initialize static mutex.
457  ///
458  /// Must be called only once.
459  void InitializeStatic(void);
460 
461  /// Initialize dynamic mutex.
462  ///
463  /// Initialize mutex if it located in heap or stack. This must be called
464  /// only once. Do not count on zeroed memory values for initializing
465  /// mutex values.
466  void InitializeDynamic(void);
467 
468  /// Destroy mutex.
470  void Destroy(void);
471 
472  friend class ::ncbi::CAutoInitializeStaticMutex;
473  friend class ::ncbi::CMutex;
474 };
475 
476 } // NCBI_NAMESPACE_MUTEX
477 
478 using NCBI_NAMESPACE_MUTEX::SSystemMutex;
479 
480 
481 /// typedefs for ease of use
483 
484 /// ...and backward compatibility
486 
487 
488 /// Determine type of system mutex initialization.
489 #if defined(SYSTEM_MUTEX_INITIALIZER)
490 
491 /// Define static fast mutex initial value.
492 # define STATIC_FAST_MUTEX_INITIALIZER \
493  { SYSTEM_MUTEX_INITIALIZER, NCBI_NS_NCBI::SSystemFastMutex::eMutexInitialized }
494 
495 /// Define static fast mutex and initialize it.
496 # define DEFINE_STATIC_FAST_MUTEX(id) \
497 static NCBI_NS_NCBI::SSystemFastMutex id = STATIC_FAST_MUTEX_INITIALIZER
498 
499 /// Declare static fast mutex.
500 # define DECLARE_CLASS_STATIC_FAST_MUTEX(id) \
501 static NCBI_NS_NCBI::SSystemFastMutex id
502 
503 /// Define fast mutex and initialize it.
504 # define DEFINE_CLASS_STATIC_FAST_MUTEX(id) \
505 NCBI_NS_NCBI::SSystemFastMutex id = STATIC_FAST_MUTEX_INITIALIZER
506 
507 /// Define static mutex initializer.
508 # define STATIC_MUTEX_INITIALIZER \
509  { STATIC_FAST_MUTEX_INITIALIZER, THREAD_SYSTEM_ID_INITIALIZER, 0 }
510 
511 /// Define static mutex and initialize it.
512 # define DEFINE_STATIC_MUTEX(id) \
513 static NCBI_NS_NCBI::SSystemMutex id = STATIC_MUTEX_INITIALIZER
514 
515 /// Declare static mutex.
516 # define DECLARE_CLASS_STATIC_MUTEX(id) \
517 static NCBI_NS_NCBI::SSystemMutex id
518 
519 /// Define mutex and initialize it.
520 # define DEFINE_CLASS_STATIC_MUTEX(id) \
521 NCBI_NS_NCBI::SSystemMutex id = STATIC_MUTEX_INITIALIZER
522 
523 #else
524 
525 /// Auto initialization for mutex will be used.
526 # define NEED_AUTO_INITIALIZE_MUTEX
527 
528 /// Define auto-initialized static fast mutex.
529 # define DEFINE_STATIC_FAST_MUTEX(id) \
530 static NCBI_NS_NCBI::CAutoInitializeStaticFastMutex id
531 
532 /// Declare auto-initialized static fast mutex.
533 # define DECLARE_CLASS_STATIC_FAST_MUTEX(id) \
534 static NCBI_NS_NCBI::CAutoInitializeStaticFastMutex id
535 
536 /// Define auto-initialized mutex.
537 # define DEFINE_CLASS_STATIC_FAST_MUTEX(id) \
538 NCBI_NS_NCBI::CAutoInitializeStaticFastMutex id
539 
540 /// Define auto-initialized static mutex.
541 # define DEFINE_STATIC_MUTEX(id) \
542 static NCBI_NS_NCBI::CAutoInitializeStaticMutex id
543 
544 /// Declare auto-initialized static mutex.
545 # define DECLARE_CLASS_STATIC_MUTEX(id) \
546 static NCBI_NS_NCBI::CAutoInitializeStaticMutex id
547 
548 /// Define auto-initialized mutex.
549 # define DEFINE_CLASS_STATIC_MUTEX(id) \
550 NCBI_NS_NCBI::CAutoInitializeStaticMutex id
551 
552 #endif
553 
554 
555 
556 #if defined(NEED_AUTO_INITIALIZE_MUTEX)
557 
558 
559 
560 /////////////////////////////////////////////////////////////////////////////
561 ///
562 /// CAutoInitializeStaticFastMutex --
563 ///
564 /// Define thread safe initializer static for SSystemFastMutex.
565 ///
566 /// Needed on platforms where system mutex struct cannot be initialized at
567 /// compile time (e.g. Win32).
568 
569 class CAutoInitializeStaticFastMutex
570 {
571 public:
572  typedef SSystemFastMutex TObject; ///< Simplified alias name for fast mutex
573 
574  /// Lock mutex.
575  void Lock(void);
576 
577  /// Unlock mutex.
578  void Unlock(void);
579 
580  /// Try locking the mutex.
581  bool TryLock(void);
582 
583  /// Return initialized mutex object.
584  operator TObject&(void);
585 
586 protected:
587  /// Initialize mutex.
588  ///
589  /// This method can be called many times it will return only after
590  /// successful initialization of m_Mutex.
592  void Initialize(void);
593 
594  /// Get initialized mutex object.
595  TObject& Get(void);
596 
597 private:
598  TObject m_Mutex; ///< Mutex object.
599 };
600 
601 
602 
603 /////////////////////////////////////////////////////////////////////////////
604 ///
605 /// CAutoInitializeStaticMutex --
606 ///
607 /// Define thread safe initializer static for SSystemMutex.
608 ///
609 /// Needed on platforms where system mutex struct cannot be initialized at
610 /// compile time (e.g. Win32).
611 
612 class CAutoInitializeStaticMutex
613 {
614 public:
615  typedef SSystemMutex TObject; ///< Simplified alias name for fast mutex
616 
617  /// Lock mutex.
618  void Lock(void);
619 
620  /// Unlock mutex.
621  void Unlock(void);
622 
623  /// Try locking the mutex.
624  bool TryLock(void);
625 
626  /// Return initialized mutex object.
627  operator TObject&(void);
628 
629 protected:
630  /// Initialize mutex.
631  ///
632  /// This method can be called many times it will return only after
633  /// successful initialization of m_Mutex.
635  void Initialize(void);
636 
637  /// Get initialized mutex object.
638  TObject& Get(void);
639 
640 private:
641  TObject m_Mutex; ///< Mutex object.
642 };
643 
644 #endif
645 
646 /////////////////////////////////////////////////////////////////////////////
647 //
648 // FAST MUTEX
649 //
650 // CFastMutex::
651 // CFastMutexGuard::
652 //
653 
654 
655 
656 /////////////////////////////////////////////////////////////////////////////
657 ///
658 /// CFastMutex --
659 ///
660 /// Simple mutex with fast lock/unlock functions.
661 ///
662 /// This mutex can be used instead of CMutex if it's guaranteed that
663 /// there is no nesting. This mutex does not check nesting or owner.
664 /// It has better performance than CMutex, but is less secure.
665 
667 {
668 public:
669  /// Constructor.
670  ///
671  /// Creates mutex handle.
672  CFastMutex(void);
673 
674  /// Destructor.
675  ///
676  /// Close mutex handle. No checks if it's still acquired.
677  ~CFastMutex(void);
678 
679  /// Define Read Lock Guard.
681 
682  /// Define Write Lock Guard.
684 
685  /// Acquire mutex for the current thread with no nesting checks.
686  void Lock(void);
687 
688  /// Release mutex with no owner or nesting checks.
689  void Unlock(void);
690 
691  /// Try locking the mutex.
692  bool TryLock(void);
693 
694  /// Get SSystemFastMutex.
695  operator SSystemFastMutex&(void);
696 
697 private:
698 #if !defined(NCBI_WIN32_THREADS)
699  /// Get handle - Unix version.
700  ///
701  /// Also used by CRWLock.
702  TSystemMutex* GetHandle(void) { return &m_Mutex.m_Handle; }
703 #elif !defined(NCBI_USE_CRITICAL_SECTION)
704  /// Get handle - Windows version.
705  ///
706  /// Also used by CRWLock.
707  HANDLE GetHandle(void) { return m_Mutex.m_Handle; }
708 #endif
709 
710  friend class CRWLock;
711 
712  /// Platform-dependent mutex handle, also used by CRWLock.
713  SSystemFastMutex m_Mutex;
714 
715  /// Private copy constructor to disallow initialization.
717 
718  /// Private assignment operator to disallow assignment.
720 };
721 
722 
723 
724 /////////////////////////////////////////////////////////////////////////////
725 //
726 // MUTEX
727 //
728 // CMutex::
729 // CMutexGuard::
730 //
731 
732 
733 
734 /////////////////////////////////////////////////////////////////////////////
735 ///
736 /// CMutex --
737 ///
738 /// Mutex that allows nesting with runtime checks.
739 ///
740 /// Allows for recursive locks by the same thread. Checks the mutex
741 /// owner before unlocking. This mutex should be used when performance
742 /// is less important than data protection. For faster performance see
743 /// CFastMutex.
744 ///
745 /// @sa
746 /// http://www.ncbi.nlm.nih.gov/books/n/toolkit/ch_core#ch_core.mutexes
747 
748 class CMutex
749 {
750 public:
751  /// Constructor.
752  CMutex(void);
753 
754  /// Destructor.
755  ///
756  /// Report error if the mutex is locked.
757  ~CMutex(void);
758 
759  /// Define Read Lock Guard.
761 
762  /// Define Write Lock Guard.
764 
765  /// Get SSystemMutex.
766  operator SSystemMutex&(void);
767 
768  /// Lock mutex.
769  ///
770  /// Operation:
771  /// - If the mutex is unlocked, then acquire it for the calling thread.
772  /// - If the mutex is acquired by this thread, then increase the
773  /// lock counter (each call to Lock() must have corresponding
774  /// call to Unlock() in the same thread).
775  /// - If the mutex is acquired by another thread, then wait until it's
776  /// unlocked, then act like a Lock() on an unlocked mutex.
777  void Lock(void);
778 
779  /// Try locking mutex.
780  ///
781  /// Try to acquire the mutex.
782  /// @return
783  /// TRUE if succesfully acquired; FALSE otherwise (e.g if the mutex is
784  /// already acquired by another thread).
785  /// @sa
786  /// Lock()
787  bool TryLock(void);
788 
789  /// Unlock mutex.
790  ///
791  /// Operation:
792  /// - If the mutex is acquired by this thread, then decrease the lock
793  /// counter.
794  /// - If the lock counter becomes zero, then release the mutex completely.
795  /// - Report error if the mutex is not locked or locked by another thread.
796  void Unlock(void);
797 
798 private:
799  SSystemMutex m_Mutex; ///< System mutex
800 
801  /// Private copy constructor to disallow initialization.
802  CMutex(const CMutex&);
803 
804  /// Private assignment operator to disallow assignment.
806 
807  friend class CRWLock; ///< Allow use of m_Mtx and m_Owner members directly
808 };
809 
810 
811 
812 /////////////////////////////////////////////////////////////////////////////
813 ///
814 /// CNoMutex --
815 ///
816 /// Fake mutex that does not lock anything.
817 ///
818 /// Allows to create template classes which use CMutex/CFastMutex/CNoMutex as
819 /// an argument. In case of CNoMutex no real locking is performed.
820 ///
821 /// @sa
822 /// CNoLock
823 
825 
826 
827 class CSpinLock;
829 
830 /////////////////////////////////////////////////////////////////////////////
831 ///
832 /// CSpinLock --
833 ///
834 /// Simple lock with lock/unlock functions even faster than in CFastMutex.
835 ///
836 /// This mutex can be used instead of CFastMutex when it's guaranteed that
837 /// lock will be always held for a short period of time. CSpinLock doesn't do
838 /// any system calls to wait for lock acquiring and relies on a fact that a
839 /// couple of thread reschedulings will be enough for another thread to
840 /// release the lock. As with CFastMutex no recursive locks are allowed.
841 
843 {
844 public:
845  CSpinLock(void);
846  ~CSpinLock(void);
847 
848  /// Define Read Lock Guard.
850  /// Define Write Lock Guard.
852 
853  /// Lock the mutex
855  void Lock(void);
856  /// Attempt to lock the mutex and return TRUE if it succeeded or FALSE if
857  /// mutex is locked by other thread.
859  bool TryLock(void);
860  /// Unlock the mutex.
861  /// There's no check that mutex is unlocked by the same thread that
862  /// locked it.
864  void Unlock(void);
865 
866  /// Check if mutex is currently locked
867  bool IsLocked(void) const;
868 
869 private:
870  /// Prohibit copying of the object
873 
874  /// Flag showing if mutex is locked (non-NULL value) or unlocked
875  /// (NULL value).
876  void* volatile m_Value;
877 };
878 
879 
880 
881 /////////////////////////////////////////////////////////////////////////////
882 //
883 // RW-LOCK
884 //
885 // CRWLock::
886 // CAutoRW::
887 // CReadLockGuard::
888 // CWriteLockGuard::
889 //
890 
891 
892 // Forward declaration of internal (platform-dependent) RW-lock representation
893 #if !NCBI_SRWLOCK_USE_NEW
894 class CInternalRWLock;
895 #endif
896 class CRWLock;
897 //class CReadLockGuard;
898 //class CWriteLockGuard;
899 
900 
901 
902 /////////////////////////////////////////////////////////////////////////////
903 ///
904 /// SSimpleReadLock --
905 ///
906 /// Acquire a read lock
907 template <class Class>
909 {
910  void operator()(Class& inst) const
911  {
912  inst.ReadLock();
913  }
914 };
915 
918 
919 
920 /////////////////////////////////////////////////////////////////////////////
921 ///
922 /// SSimpleWriteLock --
923 ///
924 /// Acquire a write lock
925 template <class Class>
927 {
928  void operator()(Class& inst) const
929  {
930  inst.WriteLock();
931  }
932 };
933 
936 
937 
938 /////////////////////////////////////////////////////////////////////////////
939 ///
940 /// CRWLock --
941 ///
942 /// Read/Write lock.
943 /// Allows multiple readers or single writer.
944 ///
945 /// NOTE about recursive locks by the same thread:
946 /// - W-after-W and R-after-R are okay.
947 /// - R-after-W is considered to be a recursive Write-lock.
948 /// - W-after-R is not allowed; note that if _DEBUG is not defined we do not
949 /// always catch W-after-R, and deadlock may happen. Test your application
950 /// in _DEBUG mode first!
951 
953 {
954 public:
955  /// Flags (passed at construction time) for fine-tuning lock behavior.
956  enum EFlags {
957  /// Forbid further readers from acquiring the lock if any writers
958  /// are waiting for it, to keep would-be writers from starving.
959  fFavorWriters = 0x1
960  };
961  typedef int TFlags; ///< binary OR of EFlags
962 
963  /// Constructor.
964  CRWLock(TFlags flags = 0);
965 
966  /// Destructor.
967  ~CRWLock(void);
968 
969  /// Define Read Lock Guard.
971 
972  /// Define Write Lock Guard.
974 
975  /// Read lock.
976  ///
977  /// Acquire the R-lock. If W-lock is already acquired by
978  /// another thread, then wait until it is released.
979  void ReadLock(void);
980 
981  /// Write lock.
982  ///
983  /// Acquire the W-lock. If R-lock or W-lock is already acquired by
984  /// another thread, then wait until it is released.
985  void WriteLock(void);
986 
987  /// Try read lock.
988  ///
989  /// Try to acquire R-lock and return immediately.
990  /// @return
991  /// TRUE if the R-lock has been successfully acquired;
992  /// FALSE, otherwise.
993  bool TryReadLock(void);
994 
995  /// Try read lock with timeout.
996  /// @param timeout
997  /// Timeout for the read lock attempt.
998  /// @return
999  /// TRUE if the R-lock has been successfully acquired;
1000  /// FALSE, otherwise.
1001  bool TryReadLock(const CTimeout& timeout);
1002 
1003  /// Try write lock.
1004  ///
1005  /// Try to acquire W-lock and return immediately.
1006  /// @return
1007  /// TRUE if the W-lock has been successfully acquired;
1008  /// FALSE, otherwise.
1009  bool TryWriteLock(void);
1010 
1011  /// Try write lock with timeout.
1012  /// @param timeout
1013  /// Timeout for the write lock attempt.
1014  /// @return
1015  /// TRUE if the W-lock has been successfully acquired;
1016  /// FALSE, otherwise.
1017  bool TryWriteLock(const CTimeout& timeout);
1018 
1019  /// Release the RW-lock.
1020  void Unlock(void);
1021 
1022 private:
1023 #if NCBI_SRWLOCK_USE_NEW
1024  mutex m_Mtx;
1025  condition_variable m_Cv;
1026  TThreadSystemID m_Owner; ///< Writer ID
1027  atomic<long> m_Count; ///< Number of readers (if >0) or writers (if <0)
1028  long m_WaitingWriters; ///< Number of writers waiting; zero if not keeping track
1029  vector<TThreadSystemID> m_Readers; ///< List of all readers to detect recursion
1030  bool m_TrackReaders;
1031  bool m_FavorWriters;
1032 
1033  bool x_HasReader(TThreadSystemID self_id);
1034  vector<TThreadSystemID>::const_iterator x_FindReader(TThreadSystemID self_id);
1035  bool x_MayAcquireForReading(TThreadSystemID self_id);
1036  bool x_TryReadLock();
1037  bool x_TryWriteLock();
1038 #else
1040  /// Keep track of which threads have read locks
1041  fTrackReaders = 0x40000000
1042  };
1043  TFlags m_Flags; ///< Configuration flags
1044  unique_ptr<CInternalRWLock> m_RW; ///< Platform-dependent RW-lock data
1045  volatile TThreadSystemID m_Owner; ///< Writer ID, one of the readers ID
1046  volatile long m_Count; ///< Number of readers (if >0) or writers (if <0)
1047  volatile unsigned int m_WaitingWriters; ///< Number of writers waiting; zero if not keeping track
1048  vector<TThreadSystemID> m_Readers; ///< List of all readers or writers
1049 
1050  bool x_MayAcquireForReading(TThreadSystemID self_id);
1051 #endif
1052 
1053  /// Private copy constructor to disallow initialization.
1054  CRWLock(const CRWLock&);
1055 
1056  /// Private assignment operator to disallow assignment.
1057  CRWLock& operator= (const CRWLock&);
1058 };
1059 
1060 
1061 class CFastRWLock;
1062 
1063 /////////////////////////////////////////////////////////////////////////////
1064 ///
1065 /// SSimpleReadUnlock --
1066 ///
1067 /// Release a read lock
1068 
1069 template <class Class>
1071 {
1072  void operator()(Class& inst) const
1073  {
1074  inst.ReadUnlock();
1075  }
1076 };
1077 
1078 typedef CGuard< CFastRWLock,
1081 
1082 /////////////////////////////////////////////////////////////////////////////
1083 ///
1084 /// SSimpleWriteUnlock --
1085 ///
1086 /// Release a write lock
1087 
1088 template <class Class>
1090 {
1091  void operator()(Class& inst) const
1092  {
1093  inst.WriteUnlock();
1094  }
1095 };
1096 
1097 typedef CGuard< CFastRWLock,
1100 
1101 
1102 /////////////////////////////////////////////////////////////////////////////
1103 ///
1104 /// CFastRWLock --
1105 ///
1106 /// Fast implementation of Read/Write lock.
1107 ///
1108 /// Allows multiple readers or single writer. Behaves similar to CRWLock
1109 /// though with some assumptions and limitations:
1110 /// - Does not try to detect recursive locks, actually any attempt to lock
1111 /// recursively will end up in undefined behavior (the only exception is
1112 /// read-after-read lock - this is ok).
1113 /// - Does not remember when and where it was actually locked, so that it will
1114 /// not be able to recover after call to ReadUnlock() or WriteUnlock() if it
1115 /// was not preceded by call to corresponding Lock() method. So the best way
1116 /// to use it is just via CFastReadGuard and CFastWriteGuard.
1117 /// - Assumes that read lock is always held for a very small amount of time,
1118 /// though write lock can be held as long as you want. Failure to comply
1119 /// with this assumption will result in heavy CPU usage when trying to
1120 /// acquire write lock while long read lock is held.
1121 /// - Assumes that write lock is taken pretty rarely so that there is no
1122 /// possibility of their overlapping (actually it easily resolves
1123 /// overlapping though with possibility of readers starvation).
1124 /// - As a consequence of previous assumption assumes that writer
1125 /// "favoredness" (see fFavorWriters in CRWLock) is always needed.
1126 /// - Assumes that there will not be too much simultaneous read locks
1127 /// acquired, at least not more than 1048576.
1128 ///
1129 /// All these assumptions and limitations allowed to make extremely
1130 /// lightweight implementation of RWLock where the most common operation -
1131 /// read lock and unlock - is performed very quickly without blocking each
1132 /// other.
1133 
1135 {
1136 public:
1139 
1142 
1143  /// Acquire read lock
1144  void ReadLock(void);
1145  /// Release read lock
1146  void ReadUnlock(void);
1147 
1148  /// Acquire write lock
1149  void WriteLock(void);
1150  /// Release write lock
1151  void WriteUnlock(void);
1152 
1153 private:
1155  CFastRWLock& operator= (const CFastRWLock&);
1156 
1157  enum {
1158  /// Number in lock count showing that write lock is acquired.
1159  kWriteLockValue = 0x100000
1160  };
1161 
1162 #if defined(NCBI_WIN32_THREADS) && defined(NCBI_FASTRWLOCK_USE_NEW)
1163  SRWLOCK m_Lock;
1164 #else
1165  /// Number of read locks acquired or value of kWriteLockValue if write
1166  /// lock was acquired
1168  /// Mutex implementing write lock
1170 #endif
1171 };
1172 
1173 
1174 
1175 class CYieldingRWLock;
1176 class CRWLockHolder;
1177 
1178 /// Type of locking provided by CYieldingRWLock
1180 {
1182  eWriteLock = 1
1183 };
1184 
1185 
1186 /// Interface for receiving messages about state changes in CRWLockHolder.
1187 /// Implementations of this interface should inherit from CObjectEx to allow
1188 /// to take smart references on them.
1190 {
1191 public:
1192  virtual ~IRWLockHolder_Listener(void);
1193 
1194  /// Callback called when lock represented by CRWLockHolder is acquired
1195  virtual void OnLockAcquired(CRWLockHolder* holder) = 0;
1196 
1197  /// Callback called when lock represented by CRWLockHolder is released
1198  virtual void OnLockReleased(CRWLockHolder* holder) = 0;
1199 };
1200 
1201 /// Types of smart references to IRWLockHolder_Listener
1204 
1205 
1206 /// Interface for factory creating CRWLockHolder objects.
1207 /// Default interface implementation supports pooling of CRWLockHolder objects
1208 /// to avoid extensive use of new/delete
1210 {
1211 public:
1212  virtual ~IRWLockHolder_Factory(void);
1213 
1214  /// Obtain new CRWLockHolder object for given CYieldingRWLock and
1215  /// necessary lock type.
1217  ERWLockType typ) = 0;
1218 
1219  /// Free unnecessary (and unreferenced by anybody) CRWLockHolder object
1220  virtual void DeleteHolder(CRWLockHolder* holder) = 0;
1221 };
1222 
1223 /// Holder of the lock inside CYieldingRWLock.
1224 /// This class should be used for 2 different reasons:
1225 /// - while IsLockAcquired() is not true the requested lock is not provided
1226 /// to you, so this object will be as a signal for you to continue operation
1227 /// - the lock is held while this object is alive, though it's always better
1228 /// to explicitly call ReleaseLock().
1230 {
1231  friend class CYieldingRWLock;
1232 
1233 public:
1234  /// Create lock holder bound to given object factory
1236 
1237  virtual ~CRWLockHolder(void);
1238 
1239  /// Get factory which this object was created from
1241 
1242  /// Get lock object that is locked by this holder
1244 
1245  /// Get type of lock held
1247 
1248  /// Check if lock requested is already granted
1249  bool IsLockAcquired(void) const;
1250 
1251  /// Release the lock held or cancel request for the lock
1252  void ReleaseLock(void);
1253 
1254  /// Add object keeping track of holder state changes
1256 
1257  /// Remove object keeping track of holder state changes
1259 
1260 public:
1261  /// Initialize holder for given CYieldingRWLock and necessary lock type.
1262  /// Method is for use only inside IRWLockHolder_Factory implementation
1264 
1265  /// Reset holder to be able to use it later (after calling Init() )
1266  void Reset(void);
1267 
1268 private:
1270  CRWLockHolder& operator= (const CRWLockHolder&);
1271 
1272  /// Callback called at the moment when lock is granted
1273  void x_OnLockAcquired(void);
1274  /// Callback called at the moment when lock is released. Method is not
1275  /// called if request for lock was canceled before it was actually
1276  /// granted.
1277  void x_OnLockReleased(void);
1278  /// "Delete" this holder after last reference was removed.
1279  /// Actually deletes using factory's DeleteHolder().
1280  virtual void DeleteThis(void);
1281 
1282 
1283  typedef list<TRWLockHolder_ListenerWeakRef> TListenersList;
1284 
1285  /// Factory created the holder
1287  /// Lock object the holder is assigned to
1289  /// Type of lock held
1291  /// Flag if lock was acquired
1293  /// Mutex for operating listeners
1295  /// List of holder listeners
1297 };
1298 
1299 /// Type that should be always used to store pointers to CRWLockHolder
1301 
1302 
1303 /// Read/write lock without blocking calls.
1304 ///
1305 /// Neither R-lock nor W-lock is bound to thread acquired it and can be
1306 /// released in any other thread. Any lock is bound to CRWLockHolder object
1307 /// only.
1308 /// Allows to exist several readers at a time or one writer. Always respects
1309 /// the time of lock request. I.e. no new readers are granted access if there
1310 /// is some writer waiting for access and no new writers are granted access if
1311 /// there is some readers waiting for access (while another writer is
1312 /// working).
1313 /// Can be customizable by instance of IRWLockHolder_Factory to adopt custom
1314 /// memory management for CRWLockHolder objects.
1316 {
1317  friend class CRWLockHolder;
1318 
1319 public:
1320  /// Create read/write lock with custom holders factory.
1321  /// By default (if factory == NULL) pooling of CRWLockHolder will be used.
1323 
1324  /// It is fatal error to destroy the object while some locks are pending.
1325  /// Thus this object should be destroyed only after calls to ReleaseLock()
1326  /// for all CRWLockHolder objects.
1327  ~CYieldingRWLock(void);
1328 
1329  /// Read lock.
1330  /// Method returns immediately no matter if lock is granted or not. If
1331  /// lock is not granted then request for lock is remembered and will be
1332  /// granted later unless CRWLockHolder::ReleaseLock() is called (or object
1333  /// is deleted).
1335 
1336  /// Write lock.
1337  /// Method returns immediately no matter if lock is granted or not. If
1338  /// lock is not granted then request for lock is remembered and will be
1339  /// granted later unless CRWLockHolder::ReleaseLock() is called (or object
1340  /// is deleted).
1342 
1343  /// General method to request read or write lock.
1344  TRWLockHolderRef AcquireLock(ERWLockType lock_type);
1345 
1346  /// Check if any type of lock on this object is held
1347  bool IsLocked(void);
1348 
1349 private:
1350  typedef deque<TRWLockHolderRef> THoldersList;
1351 
1352  /// Main implementation releasing lock
1353  void x_ReleaseLock(CRWLockHolder* holder);
1354 
1355 
1356  /// Factory creating CRWLockHolder objects
1358  /// Main locking mutex for object operations
1360  /// Number of locks granted on this object by type
1361  int m_Locks[2];
1362  /// Queue for waiting lock requests
1364 };
1365 
1366 
1367 
1368 /////////////////////////////////////////////////////////////////////////////
1369 ///
1370 /// CSemaphore --
1371 ///
1372 /// Implement the semantics of an application-wide semaphore.
1373 
1375 {
1376 public:
1377  /// Constructor.
1378  ///
1379  /// @param int_count The initial value of the semaphore.
1380  /// @param max_count Maximum value that semaphore value can be incremented to.
1381  /// NOTE: On Windows max_count can not be greater than LONG_MAX.
1382  CSemaphore(unsigned int init_count, unsigned int max_count);
1383 
1384  /// Destructor.
1385  ///
1386  /// Report error if the semaphore is locked.
1387  ~CSemaphore(void);
1388 
1389  /// Wait on semaphore.
1390  ///
1391  /// Decrement the counter by one. If the semaphore's count is zero then
1392  /// wait until it's not zero.
1393  void Wait(void);
1394 
1395  /// Timed wait.
1396  ///
1397  /// Wait up to timeout_sec + timeout_nsec/1E9 seconds for the
1398  /// semaphore's count to exceed zero. If that happens, decrement
1399  /// the counter by one and return TRUE; otherwise, return FALSE.
1400  bool TryWait(unsigned int timeout_sec = 0, unsigned int timeout_nsec = 0);
1401 
1402  /// Timed wait. Wait time specified by CTimeout.
1403  bool TryWait(const CTimeout& timeout);
1404 
1405  /// Increment the semaphore by "count".
1406  ///
1407  /// Do nothing and throw an exception if counter would exceed "max_count".
1408  void Post(unsigned int count = 1);
1409 
1410 private:
1411 #if NCBI_SEMAPHORE_USE_NEW
1412  mutex m_Mtx;
1413  condition_variable m_Cv;
1414  const unsigned int m_Max;
1415  unsigned int m_Count;
1416  bool x_TryAcquire(void);
1417 #else
1418  struct SSemaphore* m_Sem; ///< System-specific semaphore data.
1419 #endif
1420 
1421  /// Private copy constructor to disallow initialization.
1423 
1424  /// Private assignment operator to disallow assignment.
1425  CSemaphore& operator= (const CSemaphore&);
1426 };
1427 
1428 
1429 
1430 /////////////////////////////////////////////////////////////////////////////
1431 ///
1432 /// CConditionVariable --
1433 ///
1434 /// Condition variable.
1435 
1436 #if defined(NCBI_POSIX_THREADS) || (defined(NCBI_WIN32_THREADS) && (defined(NCBI_USE_CRITICAL_SECTION) || defined(NCBI_FASTMUTEX_USE_NEW)))
1437 # define NCBI_HAVE_CONDITIONAL_VARIABLE
1438 #endif
1439 
1441 {
1442 public:
1443  CConditionVariable(void);
1444  ~CConditionVariable(void);
1445 
1446  static bool IsSupported(void);
1447 
1448  /// Release mutex and lock the calling thread until the condition
1449  /// variable is signalled.
1450  ///
1451  /// @param mutex
1452  /// Mutex to release while waiting for a signal.
1453  /// At the time of the call the mutex must be locked by this thread
1454  /// exactly once. Otherwise, an exception will be thrown.
1455  /// @param deadline
1456  /// The wait will time out when system time equals or exceeds
1457  /// the absolute time specified in 'deadline'
1458  /// @return
1459  /// - TRUE when condition variable is signalled
1460  /// - FALSE if the wait has timed out
1461  /// @sa
1462  /// SignalSome, SignalAll, CConditionVariableException
1463  bool WaitForSignal
1464  (CMutex& mutex,
1465  const CDeadline& deadline = CDeadline::eInfinite);
1466 
1467  /// Release mutex and lock the calling thread until the condition
1468  /// variable is signalled.
1469  ///
1470  /// @param mutex
1471  /// Mutex to release while waiting for a signal.
1472  /// At the time of the call the mutex must be locked by this thread.
1473  /// Otherwise, an exception will be thrown.
1474  /// @param deadline
1475  /// The wait will time out when system time equals or exceeds
1476  /// the absolute time specified in 'deadline'
1477  /// @return
1478  /// TRUE when condition variable is signalled; FALSE if timed out
1479  /// @sa
1480  /// SignalSome, SignalAll, CConditionVariableException
1481  bool WaitForSignal
1482  (CFastMutex& mutex,
1483  const CDeadline& deadline = CDeadline::eInfinite);
1484 
1485  /// Wake at least one of the threads that are currently waiting on this
1486  /// condition variable (if any threads are waiting on it).
1487  /// @note
1488  /// More than one thread can be awaken.
1489  /// @sa WaitForSignal, SignalAll
1490  void SignalSome(void);
1491 
1492  /// Wake all threads that are currently waiting on the condition variable.
1493  /// @sa WaitForSignal, SignalSome
1494  void SignalAll(void);
1495 
1496 #if defined(NCBI_THREADS)
1497 private:
1498  bool x_WaitForSignal(SSystemFastMutex& mutex, const CDeadline& timeout);
1499 
1500 #if defined(NCBI_OS_MSWIN)
1501  CONDITION_VARIABLE m_ConditionVar;
1502 #else
1503  pthread_cond_t m_ConditionVar;
1504 #endif
1506  SSystemFastMutex* volatile m_WaitMutex;
1507 #endif
1508 };
1509 
1510 
1511 
1512 
1513 /////////////////////////////////////////////////////////////////////////////
1514 ///
1515 /// CConditionVariableException --
1516 ///
1517 /// Exceptions generated by condition variable.
1518 ///
1519 /// CConditionVariableException inherits its basic functionality from
1520 /// CCoreException, and defines additional error codes.
1521 ///
1522 /// @sa CConditionVariable, CCoreException
1523 
1525 {
1526 public:
1527  /// Error types that a condition variable can generate.
1528  enum EErrCode {
1529  ///< Parameter of WaitForSignal function is invalid
1530  eInvalidValue,
1531  ///< Mutex passed to WaitForSignal is not locked exactly once
1532  eMutexLockCount,
1533  ///< Mutex passed to WaitForSignal is not owned by the current thread
1534  eMutexOwner,
1535  ///< Different mutexes were supplied for concurrent WaitForSignal
1536  ///< operations on this condition variable
1537  eMutexDifferent,
1538  ///< Condition variable is not supported on this platform
1539  eUnsupported
1540  };
1541 
1542  /// Translate from the error code value to its string representation.
1543  virtual const char* GetErrCodeString(void) const override;
1544 
1545  // Standard exception boilerplate code.
1547 };
1548 
1549 /* @} */
1550 
1551 
1552 #include <corelib/ncbimtx.inl>
1553 
1554 /////////////////////////////////////////////////////////////////////////////
1555 
1557 
1558 #endif /* NCBIMTX__HPP */
CAtomicCounter_WithAutoInit –.
Definition: ncbicntr.hpp:120
CAtomicCounter –.
Definition: ncbicntr.hpp:71
CConditionVariableException –.
Definition: ncbimtx.hpp:1525
CCoreException –.
Definition: ncbiexpt.hpp:1476
CDeadline.
Definition: ncbitime.hpp:1830
CFastMutex –.
Definition: ncbimtx.hpp:667
CFastRWLock –.
Definition: ncbimtx.hpp:1135
CMutexException –.
Definition: ncbimtx.hpp:230
CMutex –.
Definition: ncbimtx.hpp:749
CNoLock is a simple no-op lock which does no real locking.
Definition: guard.hpp:215
CObject –.
Definition: ncbiobj.hpp:180
Holder of the lock inside CYieldingRWLock.
Definition: ncbimtx.hpp:1230
CRWLock –.
Definition: ncbimtx.hpp:953
CRef –.
Definition: ncbiobj.hpp:618
CSafeStaticPtr_Base::
CSemaphore –.
Definition: ncbimtx.hpp:1375
CSpinLock –.
Definition: ncbimtx.hpp:843
CThreadSystemID –.
Definition: ncbimtx.hpp:177
CTimeout – Timeout interval.
Definition: ncbitime.hpp:1693
CWeakIRef –.
Definition: ncbiobj.hpp:2806
Read/write lock without blocking calls.
Definition: ncbimtx.hpp:1316
Interface for factory creating CRWLockHolder objects.
Definition: ncbimtx.hpp:1210
Interface for receiving messages about state changes in CRWLockHolder.
Definition: ncbimtx.hpp:1190
static uch flags
#define NULL
Definition: ncbistd.hpp:225
EErrCode
Error types that an application can generate.
Definition: ncbiexpt.hpp:884
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
volatile unsigned int m_WaitingWriters
Number of writers waiting; zero if not keeping track.
Definition: ncbimtx.hpp:1047
CWriteLockGuard TWriteLockGuard
Define Write Lock Guard.
Definition: ncbimtx.hpp:973
CSpinLock(const CSpinLock &)
Prohibit copying of the object.
TWriteLockGuard CWriteLockGuard
Definition: ncbimtx.hpp:935
CGuard< CRWLock, SSimpleReadLock< CRWLock > > TReadLockGuard
Definition: ncbimtx.hpp:916
bool operator!=(const CThreadSystemID &tid) const
Non-equality operator for thread ID.
Definition: ncbimtx.hpp:199
ERWLockType
Type of locking provided by CYieldingRWLock.
Definition: ncbimtx.hpp:1180
CGuard< CFastRWLock, SSimpleReadLock< CFastRWLock >, SSimpleReadUnlock< CFastRWLock > > CFastReadGuard
Definition: ncbimtx.hpp:1080
ELockSemantics
This is for condition variables.
Definition: ncbimtx.hpp:288
CSpinGuard TWriteLockGuard
Define Write Lock Guard.
Definition: ncbimtx.hpp:851
CMutex(const CMutex &)
Private copy constructor to disallow initialization.
unique_ptr< CInternalRWLock > m_RW
Platform-dependent RW-lock data.
Definition: ncbimtx.hpp:1044
CRWLockHolder(const CRWLockHolder &)
CGuard< SSystemFastMutex > TFastMutexGuard
typedefs for ease of use
Definition: ncbimtx.hpp:388
struct SSemaphore * m_Sem
System-specific semaphore data.
Definition: ncbimtx.hpp:1418
CFastMutexGuard TReadLockGuard
Define Read Lock Guard.
Definition: ncbimtx.hpp:680
EFlags
Flags (passed at construction time) for fine-tuning lock behavior.
Definition: ncbimtx.hpp:956
CFastRWLock(const CFastRWLock &)
friend class CYieldingRWLock
Definition: ncbimtx.hpp:1231
bool TryLock(void)
Attempt to lock the mutex and return TRUE if it succeeded or FALSE if mutex is locked by other thread...
Definition: ncbimtx.cpp:2336
CFastMutex(const CFastMutex &)
Private copy constructor to disallow initialization.
void operator()(Class &inst) const
Definition: ncbimtx.hpp:1091
void Lock(void)
Acquire mutex for the current thread with no nesting checks.
bool IsInitialized(void) const
Check if mutex is initialized.
CRWLockHolder(IRWLockHolder_Factory *factory)
Create lock holder bound to given object factory.
void Lock(void)
Lock mutex.
TFastMutexGuard CFastMutexGuard
...and backward compatibility
Definition: ncbimtx.hpp:391
TID m_ID
Thread ID.
Definition: ncbimtx.hpp:182
TReadLockGuard CReadLockGuard
Definition: ncbimtx.hpp:917
bool IsLocked(void)
Check if any type of lock on this object is held.
TSystemMutex * GetHandle(void)
Get handle - Unix version.
Definition: ncbimtx.hpp:702
EMagic
Initialization flag values.
Definition: ncbimtx.hpp:280
CReadLockGuard TReadLockGuard
Define Read Lock Guard.
Definition: ncbimtx.hpp:970
void InitializeDynamic(void)
Initialize dynamic mutex.
CSpinLock & operator=(const CSpinLock &)
EInternalFlags
Definition: ncbimtx.hpp:1039
CNoLock CNoMutex
CNoMutex –.
Definition: ncbimtx.hpp:824
ERWLockType m_Type
Type of lock held.
Definition: ncbimtx.hpp:1290
~CFastMutex(void)
Destructor.
CFastMutex(void)
Constructor.
static CThreadSystemID GetCurrent(void)
Get the current thread ID.
Definition: ncbimtx.hpp:185
virtual void OnLockAcquired(CRWLockHolder *holder)=0
Callback called when lock represented by CRWLockHolder is acquired.
CGuard< CSpinLock > CSpinGuard
Definition: ncbimtx.hpp:827
bool IsLockAcquired(void) const
Check if lock requested is already granted.
CFastMutex m_WriteLock
Mutex implementing write lock.
Definition: ncbimtx.hpp:1169
~CSpinLock(void)
CFastRWLock(void)
CGuard< CRWLock, SSimpleWriteLock< CRWLock > > TWriteLockGuard
Definition: ncbimtx.hpp:934
CYieldingRWLock * GetRWLock(void) const
Get lock object that is locked by this holder.
void Reset(void)
Reset holder to be able to use it later (after calling Init() )
bool operator==(const CThreadSystemID &tid) const
Equality operator for thread ID.
Definition: ncbimtx.hpp:193
TThreadSystemID TID
Define a simpler alias for TThreadSystemID.
Definition: ncbimtx.hpp:180
CSpinLock m_ObjLock
Main locking mutex for object operations.
Definition: ncbimtx.hpp:1359
CRef< CRWLockHolder > TRWLockHolderRef
Type that should be always used to store pointers to CRWLockHolder.
Definition: ncbimtx.hpp:1300
CMutex(void)
Constructor.
CMutexGuard TWriteLockGuard
Define Write Lock Guard.
Definition: ncbimtx.hpp:763
SSystemFastMutex m_Mutex
Mutex value.
Definition: ncbimtx.hpp:411
TFlags m_Flags
Configuration flags.
Definition: ncbimtx.hpp:1043
~CMutex(void)
Destructor.
virtual void OnLockReleased(CRWLockHolder *holder)=0
Callback called when lock represented by CRWLockHolder is released.
bool IsLocked(void) const
Check if mutex is currently locked.
THoldersList m_LockWaits
Queue for waiting lock requests.
Definition: ncbimtx.hpp:1363
TRWLockHolderRef AcquireWriteLock(void)
Write lock.
CIRef< IRWLockHolder_Listener > TRWLockHolder_ListenerRef
Types of smart references to IRWLockHolder_Listener.
Definition: ncbimtx.hpp:1202
virtual CRWLockHolder * CreateHolder(CYieldingRWLock *lock, ERWLockType typ)=0
Obtain new CRWLockHolder object for given CYieldingRWLock and necessary lock type.
vector< TThreadSystemID > m_Readers
List of all readers or writers.
Definition: ncbimtx.hpp:1048
CSemaphore(const CSemaphore &)
Private copy constructor to disallow initialization.
volatile long m_Count
Number of readers (if >0) or writers (if <0)
Definition: ncbimtx.hpp:1046
SSystemFastMutex *volatile m_WaitMutex
Definition: ncbimtx.hpp:1506
void RemoveListener(IRWLockHolder_Listener *listener)
Remove object keeping track of holder state changes.
SSystemFastMutex m_Mutex
Platform-dependent mutex handle, also used by CRWLock.
Definition: ncbimtx.hpp:713
~CFastRWLock(void)
IRWLockHolder_Factory * m_Factory
Factory created the holder.
Definition: ncbimtx.hpp:1286
bool TryLock(void)
Try locking mutex.
CGuard< SSystemMutex > TMutexGuard
typedefs for ease of use
Definition: ncbimtx.hpp:482
void Set(const CThreadSystemID &tid) volatile
volatile versions of above methods
Definition: ncbimtx.hpp:205
TListenersList m_Listeners
List of holder listeners.
Definition: ncbimtx.hpp:1296
IRWLockHolder_Factory * m_Factory
Factory creating CRWLockHolder objects.
Definition: ncbimtx.hpp:1357
bool Is(const CThreadSystemID &tid) const volatile
Definition: ncbimtx.hpp:209
bool IsNot(const CThreadSystemID &tid) const volatile
Definition: ncbimtx.hpp:213
pthread_mutex_t TSystemMutex
Define a platform independent system mutex.
Definition: ncbimtx.hpp:119
void AddListener(IRWLockHolder_Listener *listener)
Add object keeping track of holder state changes.
volatile EMagic m_Magic
Magic flag.
Definition: ncbimtx.hpp:284
CAtomicCounter_WithAutoInit m_WaitCounter
Definition: ncbimtx.hpp:1505
CFastMutexGuard TWriteLockGuard
Define Write Lock Guard.
Definition: ncbimtx.hpp:683
volatile TThreadSystemID m_Owner
Writer ID, one of the readers ID.
Definition: ncbimtx.hpp:1045
void Init(CYieldingRWLock *lock, ERWLockType typ)
Initialize holder for given CYieldingRWLock and necessary lock type.
bool IsUninitialized(void) const
Check if mutex is un-initialized.
void Unlock(void)
Unlock the mutex.
Definition: ncbimtx.cpp:2342
void ReleaseLock(void)
Release the lock held or cancel request for the lock.
CRWLock(const CRWLock &)
Private copy constructor to disallow initialization.
CMutex & operator=(const CMutex &)
Private assignment operator to disallow assignment.
virtual void DeleteHolder(CRWLockHolder *holder)=0
Free unnecessary (and unreferenced by anybody) CRWLockHolder object.
CWeakIRef< IRWLockHolder_Listener > TRWLockHolder_ListenerWeakRef
Definition: ncbimtx.hpp:1203
NCBI_EXCEPTION_DEFAULT(CConditionVariableException, CCoreException)
NCBI_EXCEPTION_DEFAULT(CMutexException, CCoreException)
CAtomicCounter m_LockCount
Number of read locks acquired or value of kWriteLockValue if write lock was acquired.
Definition: ncbimtx.hpp:1167
CSpinGuard TReadLockGuard
Define Read Lock Guard.
Definition: ncbimtx.hpp:849
CFastMutex & operator=(const CFastMutex &)
Private assignment operator to disallow assignment.
void Unlock(void)
Unlock mutex.
bool IsUninitialized(void) const
Check if mutex is un-initialized.
void InitializeStatic(void)
Initialize static mutex.
SSystemMutex m_Mutex
System mutex.
Definition: ncbimtx.hpp:799
void operator()(Class &inst) const
Definition: ncbimtx.hpp:928
void operator()(Class &inst) const
Definition: ncbimtx.hpp:910
CFastWriteGuard TWriteLockGuard
Definition: ncbimtx.hpp:1138
deque< TRWLockHolderRef > THoldersList
Definition: ncbimtx.hpp:1350
IRWLockHolder_Factory * GetFactory(void) const
Get factory which this object was created from.
bool IsInitialized(void) const
Check if mutex is initialized.
void Lock(void)
Lock the mutex.
Definition: ncbimtx.cpp:2326
list< TRWLockHolder_ListenerWeakRef > TListenersList
Definition: ncbimtx.hpp:1283
TMutexGuard CMutexGuard
...and backward compatibility
Definition: ncbimtx.hpp:485
CYieldingRWLock * m_Lock
Lock object the holder is assigned to.
Definition: ncbimtx.hpp:1288
void operator()(Class &inst) const
Definition: ncbimtx.hpp:1072
CONDITION_VARIABLE m_ConditionVar
Definition: ncbimtx.hpp:1501
pthread_t TThreadSystemID
Define platform-dependent thread ID type.
atomic< TThreadSystemID > m_Owner
Platform-dependent owner thread ID.
Definition: ncbimtx.hpp:413
TRWLockHolderRef AcquireReadLock(void)
Read lock.
CMutexGuard TReadLockGuard
Define Read Lock Guard.
Definition: ncbimtx.hpp:760
atomic< int > m_Count
# of recursive (in the same thread) locks
Definition: ncbimtx.hpp:415
CFastReadGuard TReadLockGuard
Definition: ncbimtx.hpp:1137
CGuard< CFastRWLock, SSimpleWriteLock< CFastRWLock >, SSimpleWriteUnlock< CFastRWLock > > CFastWriteGuard
Definition: ncbimtx.hpp:1099
CSpinLock m_ObjLock
Mutex for operating listeners.
Definition: ncbimtx.hpp:1294
int TFlags
binary OR of EFlags
Definition: ncbimtx.hpp:961
void *volatile m_Value
Flag showing if mutex is locked (non-NULL value) or unlocked (NULL value).
Definition: ncbimtx.hpp:876
TSystemMutex m_Handle
Mutex handle.
Definition: ncbimtx.hpp:277
void Unlock(void)
Release mutex with no owner or nesting checks.
void CheckInitialized(void) const
Check initialized value of mutex.
bool m_LockAcquired
Flag if lock was acquired.
Definition: ncbimtx.hpp:1292
static TThreadSystemID GetCurrentThreadSystemID(void)
Get the current thread ID.
Definition: ncbimtx.hpp:152
bool TryLock(void)
Try locking the mutex.
ERWLockType GetLockType(void) const
Get type of lock held.
#define NCBI_NAMESPACE_MUTEX
Definition: ncbimtx.hpp:147
CSpinLock(void)
@ eWriteLock
Definition: ncbimtx.hpp:1182
@ eReadLock
Definition: ncbimtx.hpp:1181
@ eTryLock
Attempted lock error.
Definition: ncbimtx.hpp:236
@ eUnlock
Unlock error.
Definition: ncbimtx.hpp:235
@ eLock
Lock error.
Definition: ncbimtx.hpp:234
@ eOwner
Not owned error.
Definition: ncbimtx.hpp:237
@ eInfinite
Infinite deadline.
Definition: ncbitime.hpp:1834
#define NCBI_XNCBI_EXPORT
Definition: ncbi_export.h:1283
#define HANDLE
An abstraction for a file handle.
Definition: mdb.c:383
const TYPE & Get(const CNamedParameterList *param)
@ eUninitialized
Definition: ncbidiag.cpp:898
Portable reference counted smart and weak pointers using CWeakRef, CRef, CObject and CObjectEx.
Multi-threading configuration.
Defines: CTimeFormat - storage class for time format.
SSimpleReadLock –.
Definition: ncbimtx.hpp:909
SSimpleReadUnlock –.
Definition: ncbimtx.hpp:1071
SSimpleWriteLock –.
Definition: ncbimtx.hpp:927
SSimpleWriteUnlock –.
Definition: ncbimtx.hpp:1090
Modified on Mon Jul 22 05:03:16 2024 by modify_doxy.py rev. 669887