DSL
Mutex.h
1 //@AUTOHEADER@BEGIN@
2 /***********************************************************************\
3 | Drift Standard Libraries v1.01 |
4 | Copyright 2010-2023 Drift Solutions / Indy Sams |
5 | Docs and more information available at https://www.driftsolutions.dev |
6 | This file released under the 3-clause BSD license, |
7 | see included DSL.LICENSE.TXT file for details. |
8 \***********************************************************************/
9 //@AUTOHEADER@END@
10 
11 #ifndef _INCLUDE_MUTEX_H_
12 #define _INCLUDE_MUTEX_H_
13 
14 #include <drift/Threading.h>
15 
25 #if !defined(DSL_DEFAULT_MUTEX_TIMEOUT)
26 #define DSL_DEFAULT_MUTEX_TIMEOUT -1
27 #endif
28 
32 class DSL_API_CLASS DSL_Mutex_Base {
33 public:
34  virtual bool Lock(int timeout)=0;
35  virtual bool Lock()=0;
36  virtual void Release()=0;
37 
38  virtual void SetLockTimeout(int timeout)=0;
39  virtual bool IsLocked()=0;
40  virtual bool IsLockMine()=0;
41 
42  virtual THREADIDTYPE LockingThread()=0;
43 
44  virtual ~DSL_Mutex_Base(){}
45 };
46 
47 #ifndef DOXYGEN_SKIP
48 
49 #if defined(WIN32) || defined(XBOX)
50 
51 class DSL_API_CLASS DSL_Mutex_Win32CS : public DSL_Mutex_Base {
52  private:
53  THREADIDTYPE LockingThreadID;
54  int refcnt;
55  int lock_timeout;
56  CRITICAL_SECTION cs;
57  public:
58  DSL_Mutex_Win32CS(int timeout = DSL_DEFAULT_MUTEX_TIMEOUT);
59  virtual ~DSL_Mutex_Win32CS();
60 
61  bool Lock(int timeout);
62  bool Lock();
63  void Release();
64 
65  void SetLockTimeout(int timeout) { // -1 = no timeout
66  lock_timeout = timeout;
67  }
68  bool IsLocked();
69  bool IsLockMine();
70 
71  THREADIDTYPE LockingThread();
72 };
73 
74 class DSL_API_CLASS DSL_Mutex_Win32Mutex : public DSL_Mutex_Base {
75  private:
76  THREADIDTYPE LockingThreadID;
77  int refcnt;
78  int lock_timeout;
79  HANDLE hMutex;
80  public:
81  DSL_Mutex_Win32Mutex(int timeout = DSL_DEFAULT_MUTEX_TIMEOUT, const char * name = NULL);
82  virtual ~DSL_Mutex_Win32Mutex();
83 
84  bool Lock(int timeout);
85  bool Lock();
86  void Release();
87 
88  void SetLockTimeout(int timeout) { // -1 = no timeout
89  lock_timeout = timeout;
90  }
91  bool IsLocked();
92  bool IsLockMine();
93 
94  THREADIDTYPE LockingThread();
95 };
96 
97 #if DSL_DEFAULT_MUTEX_TIMEOUT > 0
98 #define DSL_Mutex DSL_Mutex_Win32Mutex
99 #define DSL_TimedMutex DSL_Mutex_Win32Mutex
100 #else
101 #define DSL_Mutex DSL_Mutex_Win32CS
102 #define DSL_TimedMutex DSL_Mutex_Win32Mutex
103 #endif
104 
105 #else // defined(WIN32) || defined(XBOX)
106 
107 class DSL_API_CLASS DSL_Mutex_pthreads : public DSL_Mutex_Base {
108  private:
109  THREADIDTYPE LockingThreadID;
110  int refcnt;
111  int lock_timeout;
112  pthread_mutex_t hMutex;
113  public:
114  DSL_Mutex_pthreads(int timeout = DSL_DEFAULT_MUTEX_TIMEOUT);
115  virtual ~DSL_Mutex_pthreads();
116 
117  bool Lock(int timeout);
118  bool Lock();
119  void Release();
120 
121  void SetLockTimeout(int timeout) { // -1 = no timeout
122  lock_timeout = timeout;
123  }
124  bool IsLocked();
125  bool IsLockMine();
126 
127  THREADIDTYPE LockingThread();
128 };
129 
130 #define DSL_Mutex DSL_Mutex_pthreads
131 #define DSL_TimedMutex DSL_Mutex_pthreads
132 #endif // defined(WIN32) || defined(XBOX)
133 
134 #endif // DOXYGEN_SKIP
135 
136 #ifdef DEBUG_MUTEX
137 #define LockMutex(x) { \
138  OutputDebugString("DSL_Mutex::Lock()\n"); \
139  printf("DSL_Mutex::Lock(%s, %d)\n", __FILE__, __LINE__); \
140  x.Lock(); \
141  OutputDebugString("DSL_Mutex::Locked()\n"); \
142  printf("DSL_Mutex::Locked(%s, %d)\n", __FILE__, __LINE__); \
143 }
144 #define LockMutexPtr(x) { \
145  OutputDebugString("DSL_Mutex::Lock()\n"); \
146  printf("DSL_Mutex::Lock(%s, %d)\n", __FILE__, __LINE__); \
147  x->Lock(); \
148  OutputDebugString("DSL_Mutex::Locked()\n"); \
149  printf("DSL_Mutex::Locked(%s, %d)\n", __FILE__, __LINE__); \
150 }
151 #define RelMutex(x) { printf("DSL_Mutex::Release(%s, %d)\n", __FILE__, __LINE__); x.Release(); }
152 #define RelMutexPtr(x) { OutputDebugString("DSL_Mutex::Release()\n"); printf("DSL_Mutex::Release(%s, %d)\n", __FILE__, __LINE__); x->Release(); printf("DSL_Mutex::Released(%s, %d)\n", __FILE__, __LINE__); OutputDebugString("DSL_Mutex::Released()\n"); }
153 #else
154 #define LockMutex(x) x.Lock()
155 #define LockMutexPtr(x) x->Lock()
156 #define TryLockMutex(x, y) x.Lock(y)
157 #define TryLockMutexPtr(x, y) x->Lock(y)
158 #define RelMutex(x) x.Release()
159 #define RelMutexPtr(x) x->Release()
160 #endif
161 
166 private:
167 #ifdef DEBUG_MUTEX
168  string fn;
169  int line;
170 #endif
171  DSL_Mutex_Base * hMutex;
172 public:
173 #ifdef DEBUG_MUTEX
174  DSL_MutexLocker(DSL_Mutex_Base * mutex, string pfn = __FILE__, int pline = __LINE__) {
175  hMutex = mutex;
176  fn = pfn;
177  line = pline;
178  OutputDebugString("DSL_Mutex::Lock()\n");
179  printf("DSL_Mutex::Lock(%s, %d)\n", fn.c_str(), line);
180  hMutex->Lock();
181  OutputDebugString("DSL_Mutex::Locked()\n");
182  printf("DSL_Mutex::Locked(%s, %d)\n", fn.c_str(), line);
183  }
184  ~DSL_MutexLocker() {
185  OutputDebugString("DSL_Mutex::Release()\n");
186  printf("DSL_Mutex::Release(%s, %d)\n", fn.c_str(), line);
187  if (hMutex->IsLockMine()) {
188  hMutex->Release();
189  }
190  printf("DSL_Mutex::Released(%s, %d)\n", fn.c_str(), line);
191  OutputDebugString("DSL_Mutex::Released()\n");
192  }
193 #else
195  hMutex = mutex;
196  LockMutexPtr(mutex);
197  }
198  ~DSL_MutexLocker() {
199  if (hMutex->IsLockMine()) {
200  RelMutexPtr(hMutex);
201  }
202  }
203 #endif
204 };
205 
206 #ifdef DEBUG_MUTEX
207 #define AutoMutex(x) DSL_MutexLocker MAKE_UNIQUE_NAME (&x, __FILE__, __LINE__)
208 #define AutoMutexPtr(x) DSL_MutexLocker MAKE_UNIQUE_NAME (x, __FILE__, __LINE__)
209 #else
210 #define AutoMutex(x) DSL_MutexLocker MAKE_UNIQUE_NAME (&x)
211 #define AutoMutexPtr(x) DSL_MutexLocker MAKE_UNIQUE_NAME (x)
212 #endif
213 
216 #ifndef DOXYGEN_SKIP
217 
218 // *** DO NOT USE THIS, FOR DSL INTERNAL USE ONLY ***
219 DSL_Mutex * dslMutex();
220 
221 #endif // DOXYGEN_SKIP
222 
223 #endif // _INCLUDE_MUTEX_H_