0030569: Foundation Classes - NCollection_Shared lacks inclusion of NCollection_Defin...
[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 <sys/errno.h>
28   #include <unistd.h>
29   #include <time.h>
30 #endif
31
32 /** 
33   * @brief Mutex: a class to synchronize access to shared data. 
34   *
35   * This is simple encapsulation of tools provided by the
36   * operating system to syncronize access to shared data 
37   * from threads within one process.
38   *
39   * Current implementation is very simple and straightforward;
40   * it is just a wrapper around POSIX pthread librray on UNIX/Linux,
41   * and CRITICAL_SECTIONs on Windows NT. It does not provide any
42   * advanced functionaly such as recursive calls to the same mutex from 
43   * within one thread (such call will froze the execution).
44   *
45   * Note that all the methods of that class are made inline, in order
46   * to keep maximal performance. This means that a library using the mutex
47   * might need to be linked to threads library directly.
48   *
49   * The typical use of this class should be as follows:
50   * - create instance of the class Standard_Mutex in the global scope
51   *   (whenever possible, or as a field of your class)
52   * - create instance of class Standard_Mutex::Sentry using that Mutex
53   *   when entering critical section
54   *
55   * Note that this class provides one feature specific to Open CASCADE:
56   * safe unlocking the mutex when signal is raised and converted to OCC
57   * exceptions (Note that with current implementation of this functionality
58   * on UNIX and Linux, C longjumps are used for that, thus destructors of 
59   * classes are not called automatically).
60   * 
61   * To use this feature, call RegisterCallback() after Lock() or successful
62   * TryLock(), and UnregisterCallback() before Unlock() (or use Sentry classes). 
63   */
64
65 class Standard_Mutex : public Standard_ErrorHandler::Callback
66 {
67 public:
68   /**
69     * @brief Simple sentry class providing convenient interface to mutex.
70     * 
71     * Provides automatic locking and unlocking a mutex in its constructor
72     * and destructor, thus ensuring correct unlock of the mutex even in case of 
73     * raising an exception or signal from the protected code.
74     *
75     * Create instance of that class when entering critical section.
76     */
77   class Sentry 
78   {
79   public:
80
81     //! Constructor - initializes the sentry object by reference to a
82     //! mutex (which must be initialized) and locks the mutex immediately
83     Sentry (Standard_Mutex& theMutex)
84     : myMutex (&theMutex)
85     {
86       Lock();
87     }
88     
89     //! Constructor - initializes the sentry object by pointer to a
90     //! mutex and locks the mutex if its pointer is not NULL
91     Sentry (Standard_Mutex* theMutex)
92     : myMutex (theMutex)
93     {
94       if (myMutex != NULL)
95       {
96         Lock();
97       }
98     }
99     //! Destructor - unlocks the mutex if already locked.
100     ~Sentry()
101     {
102       if (myMutex != NULL)
103       {
104         Unlock();
105       }
106     }
107
108   private:
109
110     //! Lock the mutex
111     void Lock()
112     {
113       myMutex->Lock();
114       myMutex->RegisterCallback();
115     }
116
117     //! Unlock the mutex
118     void Unlock()
119     {
120       myMutex->UnregisterCallback();
121       myMutex->Unlock();
122     }
123
124     //! This method should not be called (prohibited).
125     Sentry (const Sentry &);
126     //! This method should not be called (prohibited).
127     Sentry& operator = (const Sentry &);
128
129   private:
130     Standard_Mutex* myMutex;
131   };
132    
133 public:
134   
135   //! Constructor: creates a mutex object and initializes it.
136   //! It is strongly recommended that mutexes were created as 
137   //! static objects whenever possible.
138   Standard_EXPORT Standard_Mutex ();
139   
140   //! Destructor: destroys the mutex object
141   Standard_EXPORT ~Standard_Mutex ();
142   
143   //! Method to lock the mutex; waits until the mutex is released
144   //! by other threads, locks it and then returns
145   Standard_EXPORT void Lock ();
146
147   //! Method to test the mutex; if the mutex is not hold by other thread,
148   //! locks it and returns True; otherwise returns False without waiting
149   //! mutex to be released.
150   Standard_EXPORT Standard_Boolean TryLock ();
151
152   //! Method to unlock the mutex; releases it to other users
153   void Unlock ();
154
155 private:
156
157   //! Callback method to unlock the mutex if OCC exception or signal is raised
158   Standard_EXPORT virtual void DestroyCallback() Standard_OVERRIDE;
159   
160   //! This method should not be called (prohibited).
161   Standard_Mutex (const Standard_Mutex &);
162   //! This method should not be called (prohibited).
163   Standard_Mutex& operator = (const Standard_Mutex &);
164   
165 private:
166 #if (defined(_WIN32) || defined(__WIN32__))
167   CRITICAL_SECTION myMutex;
168 #else
169   pthread_mutex_t myMutex;
170 #endif  
171 };
172
173 // Implementation of the method Unlock is inline, since it is 
174 // just a shortcut to system function
175 inline void Standard_Mutex::Unlock ()
176 {
177 #if (defined(_WIN32) || defined(__WIN32__))
178   LeaveCriticalSection (&myMutex);
179 #else
180   pthread_mutex_unlock (&myMutex);
181 #endif
182 }
183
184 #endif /* _Standard_Mutex_HeaderFile */