0031363: Documentation - broken Doxygen documentation of header files in Standard...
[occt.git] / src / Standard / Standard_Mutex.hxx
1 // Created on: 2005-04-10
2 // Created by: Andrey BETENEV
3 // Copyright (c) 2005-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef _Standard_Mutex_HeaderFile
17 #define _Standard_Mutex_HeaderFile
18
19 #include <Standard_Integer.hxx>
20 #include <Standard_Boolean.hxx>
21 #include <Standard_ErrorHandler.hxx>
22
23 #if defined(_WIN32)
24   #include <windows.h>
25 #else
26   #include <pthread.h>
27   #include <unistd.h>
28   #include <time.h>
29 #endif
30
31 /** 
32   * @brief Mutex: a class to synchronize access to shared data. 
33   *
34   * This is simple encapsulation of tools provided by the
35   * operating system to syncronize access to shared data 
36   * from threads within one process.
37   *
38   * Current implementation is very simple and straightforward;
39   * it is just a wrapper around POSIX pthread librray on UNIX/Linux,
40   * and CRITICAL_SECTIONs on Windows NT. It does not provide any
41   * advanced functionaly such as recursive calls to the same mutex from 
42   * within one thread (such call will froze the execution).
43   *
44   * Note that all the methods of that class are made inline, in order
45   * to keep maximal performance. This means that a library using the mutex
46   * might need to be linked to threads library directly.
47   *
48   * The typical use of this class should be as follows:
49   * - create instance of the class Standard_Mutex in the global scope
50   *   (whenever possible, or as a field of your class)
51   * - create instance of class Standard_Mutex::Sentry using that Mutex
52   *   when entering critical section
53   *
54   * Note that this class provides one feature specific to Open CASCADE:
55   * safe unlocking the mutex when signal is raised and converted to OCC
56   * exceptions (Note that with current implementation of this functionality
57   * on UNIX and Linux, C longjumps are used for that, thus destructors of 
58   * classes are not called automatically).
59   * 
60   * To use this feature, call RegisterCallback() after Lock() or successful
61   * TryLock(), and UnregisterCallback() before Unlock() (or use Sentry classes). 
62   */
63
64 class Standard_Mutex : public Standard_ErrorHandler::Callback
65 {
66 public:
67   /**
68     * @brief Simple sentry class providing convenient interface to mutex.
69     * 
70     * Provides automatic locking and unlocking a mutex in its constructor
71     * and destructor, thus ensuring correct unlock of the mutex even in case of 
72     * raising an exception or signal from the protected code.
73     *
74     * Create instance of that class when entering critical section.
75     */
76   class Sentry 
77   {
78   public:
79
80     //! Constructor - initializes the sentry object by reference to a
81     //! mutex (which must be initialized) and locks the mutex immediately
82     Sentry (Standard_Mutex& theMutex)
83     : myMutex (&theMutex)
84     {
85       Lock();
86     }
87     
88     //! Constructor - initializes the sentry object by pointer to a
89     //! mutex and locks the mutex if its pointer is not NULL
90     Sentry (Standard_Mutex* theMutex)
91     : myMutex (theMutex)
92     {
93       if (myMutex != NULL)
94       {
95         Lock();
96       }
97     }
98     //! Destructor - unlocks the mutex if already locked.
99     ~Sentry()
100     {
101       if (myMutex != NULL)
102       {
103         Unlock();
104       }
105     }
106
107   private:
108
109     //! Lock the mutex
110     void Lock()
111     {
112       myMutex->Lock();
113       myMutex->RegisterCallback();
114     }
115
116     //! Unlock the mutex
117     void Unlock()
118     {
119       myMutex->UnregisterCallback();
120       myMutex->Unlock();
121     }
122
123     //! This method should not be called (prohibited).
124     Sentry (const Sentry &);
125     //! This method should not be called (prohibited).
126     Sentry& operator = (const Sentry &);
127
128   private:
129     Standard_Mutex* myMutex;
130   };
131    
132 public:
133   
134   //! Constructor: creates a mutex object and initializes it.
135   //! It is strongly recommended that mutexes were created as 
136   //! static objects whenever possible.
137   Standard_EXPORT Standard_Mutex ();
138   
139   //! Destructor: destroys the mutex object
140   Standard_EXPORT ~Standard_Mutex ();
141   
142   //! Method to lock the mutex; waits until the mutex is released
143   //! by other threads, locks it and then returns
144   Standard_EXPORT void Lock ();
145
146   //! Method to test the mutex; if the mutex is not hold by other thread,
147   //! locks it and returns True; otherwise returns False without waiting
148   //! mutex to be released.
149   Standard_EXPORT Standard_Boolean TryLock ();
150
151   //! Method to unlock the mutex; releases it to other users
152   void Unlock ();
153
154 private:
155
156   //! Callback method to unlock the mutex if OCC exception or signal is raised
157   Standard_EXPORT virtual void DestroyCallback() Standard_OVERRIDE;
158   
159   //! This method should not be called (prohibited).
160   Standard_Mutex (const Standard_Mutex &);
161   //! This method should not be called (prohibited).
162   Standard_Mutex& operator = (const Standard_Mutex &);
163   
164 private:
165 #if (defined(_WIN32) || defined(__WIN32__))
166   CRITICAL_SECTION myMutex;
167 #else
168   pthread_mutex_t myMutex;
169 #endif  
170 };
171
172 // Implementation of the method Unlock is inline, since it is 
173 // just a shortcut to system function
174 inline void Standard_Mutex::Unlock ()
175 {
176 #if (defined(_WIN32) || defined(__WIN32__))
177   LeaveCriticalSection (&myMutex);
178 #else
179   pthread_mutex_unlock (&myMutex);
180 #endif
181 }
182
183 #endif /* _Standard_Mutex_HeaderFile */