PTLib  Version 2.18.8
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mutex.h
Go to the documentation of this file.
1 /*
2  * mutex.h
3  *
4  * Mutual exclusion thread synchonisation class.
5  *
6  * Portable Windows Library
7  *
8  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Portable Windows Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25  * All Rights Reserved.
26  *
27  * Contributor(s): ______________________________________.
28  */
29 
30 #ifndef PTLIB_MUTEX_H
31 #define PTLIB_MUTEX_H
32 
33 #ifdef P_USE_PRAGMA
34 #pragma interface
35 #endif
36 
37 #include <ptlib/atomic.h>
38 #include <ptlib/semaphor.h>
39 
40 
42 {
43  protected:
48 
51  const PDebugLocation & location,
52  unsigned timeout
53  );
56  void Construct(unsigned timeout);
57 
58 #if PTRACING
59  void Constructed(const PObject & mutex) const;
60  void Destroyed(const PObject & mutex) const;
61  #define PMUTEX_CONSTRUCTED() Constructed(*this)
62  #define PMUTEX_DESTROYED() Destroyed(*this)
63 #else
64  #define PMUTEX_CONSTRUCTED()
65  #define PMUTEX_DESTROYED()
66 #endif
67 
68  void PrintOn(ostream &strm) const;
69  void ExcessiveLockPhantom(const PObject & mutex) const;
70  virtual void AcquiredLock(uint64_t startWaitCycle, bool readOnly, const PDebugLocation & location);
71  virtual void ReleasedLock(const PObject & mutex, uint64_t startHeldSamplePoint, bool readOnly, const PDebugLocation & location);
72 
73  static unsigned MinDeadlockTime(unsigned waitTime);
74 
75  public:
76  void SetLocationName(const char * name) { m_location.m_extra = name; }
77 };
78 
79 
102 {
104  public:
105  /* Create a new mutex.
106  Initially the mutex will not be "set", so the first call to Wait() will
107  never wait.
108 
109  The name/line parameters are used for deadlock detection debugging.
110  */
111  explicit PTimedMutex();
112  explicit PTimedMutex(
113  const PDebugLocation & location,
114  unsigned timeout = 0
115  );
116 
120  PTimedMutex(const PTimedMutex & mutex);
121 
125  PTimedMutex & operator=(const PTimedMutex &) { return *this; }
126 
128  ~PTimedMutex();
129 
132  virtual void Wait();
133 
139  virtual PBoolean Wait(
140  const PTimeInterval & timeout // Amount of time to wait.
141  );
142 
145  virtual void Signal();
146 
150  PINLINE bool Try() { return Wait(0); }
151 
152  virtual void PrintOn(ostream &strm) const;
153 
154  static unsigned ExcessiveLockWaitTime;
156  {
161  };
163 #if PTRACING
164  static unsigned CtorDtorLogLevel;
165 #endif
166 
167  protected:
168  PThreadIdentifier m_lockerId;
169  PThreadIdentifier m_lastLockerId;
170  PUniqueThreadIdentifier m_lastUniqueId;
171  unsigned m_lockCount;
172 
173  void Construct();
174  void PlatformConstruct();
175  bool PlatformWait(const PTimeInterval & timeout);
176  void PlatformSignal(const PDebugLocation * location);
177  void InternalWait(const PDebugLocation * location);
178  void InternalWaitComplete(uint64_t startWaitCycle, const PDebugLocation * location);
179  bool InternalSignal(const PDebugLocation * location);
180 
181 // Include platform dependent part of class
182 #ifdef _WIN32
183 #include "msos/ptlib/mutex.h"
184 #else
185 #include "unix/ptlib/mutex.h"
186 #endif
187 };
188 
190 
192 
193 #define PDECLARE_MUTEX_ARG_1(var) struct PTimedMutex_##var : PTimedMutex { PTimedMutex_##var() : PTimedMutex(P_DEBUG_LOCATION) { } } var
194 #define PDECLARE_MUTEX_ARG_2(var,nam) struct PTimedMutex_##var : PTimedMutex { PTimedMutex_##var() : PTimedMutex(#nam ) { } } var
195 #define PDECLARE_MUTEX_ARG_3(var,nam,to) struct PTimedMutex_##var : PTimedMutex { PTimedMutex_##var() : PTimedMutex(#nam,to ) { } } var
196 
197 #define PDECLARE_MUTEX_PART1(narg, args) PDECLARE_MUTEX_PART2(narg, args)
198 #define PDECLARE_MUTEX_PART2(narg, args) PDECLARE_MUTEX_ARG_##narg args
199 
200 #define PDECLARE_MUTEX(...) PDECLARE_MUTEX_PART1(PARG_COUNT(__VA_ARGS__), (__VA_ARGS__))
201 
202 #if PTRACING
203  class PInstrumentedMutex : PDebugLocation, public PTimedMutex
204  {
205  public:
206  PInstrumentedMutex(
207  const char * baseName,
208  const char * file,
209  unsigned line,
210  const char * waitName,
211  const char * heldName,
212  unsigned waitTime,
213  unsigned heldTime,
214  unsigned throttleTime = 10000,
215  unsigned throttledLogLevel = 2,
216  unsigned unthrottledLogLevel = 6,
217  unsigned thresholdPercent = 5,
218  unsigned maxHistory = 0
219  ) : PDebugLocation(file, line, baseName)
220  , PTimedMutex(this, MinDeadlockTime(waitTime))
221  , m_timeWaitContext(PDebugLocation(file, line, waitName), waitTime, throttleTime, throttledLogLevel, unthrottledLogLevel, thresholdPercent, maxHistory)
222  , m_timeHeldContext(PDebugLocation(file, line, heldName), heldTime, throttleTime, throttledLogLevel, unthrottledLogLevel, thresholdPercent, maxHistory)
223  { }
224 
225  void SetWaitThrottleTime(unsigned throttleTime) { m_timeWaitContext.SetThrottleTime(throttleTime); }
226  void SetWaitThrottledLogLevel(unsigned throttledLogLevel) { m_timeWaitContext.SetThrottledLogLevel(throttledLogLevel); }
227  void SetWaitUnthrottledLogLevel(unsigned unthrottledLogLevel) { m_timeWaitContext.SetUnthrottledLogLevel(unthrottledLogLevel); }
228  void SetWaitThresholdPercent(unsigned thresholdPercent) { m_timeWaitContext.SetThresholdPercent(thresholdPercent); }
229  void SetWaitMaxHistory(unsigned maxHistory) { m_timeWaitContext.SetMaxHistory(maxHistory); }
230 
231  void SetHeldThrottleTime(unsigned throttleTime) { m_timeHeldContext.SetThrottleTime(throttleTime); }
232  void SetHeldThrottledLogLevel(unsigned throttledLogLevel) { m_timeHeldContext.SetThrottledLogLevel(throttledLogLevel); }
233  void SetHeldUnthrottledLogLevel(unsigned unthrottledLogLevel) { m_timeHeldContext.SetUnthrottledLogLevel(unthrottledLogLevel); }
234  void SetHeldThresholdPercent(unsigned thresholdPercent) { m_timeHeldContext.SetThresholdPercent(thresholdPercent); }
235  void SetHeldMaxHistory(unsigned maxHistory) { m_timeHeldContext.SetMaxHistory(maxHistory); }
236 
237  virtual bool InstrumentedWait(const PTimeInterval & timeout, const PDebugLocation & location);
238  virtual void InstrumentedSignal(const PDebugLocation & location) { PlatformSignal(&location); }
239 
240  protected:
241  virtual void AcquiredLock(uint64_t startWaitCycle, bool readOnly, const PDebugLocation & location);
242  virtual void ReleasedLock(const PObject & mutex, uint64_t startHeldSamplePoint, bool readOnly, const PDebugLocation & location);
243 
244  PProfiling::TimeScope m_timeWaitContext;
245  PProfiling::TimeScope m_timeHeldContext;
246  };
247 
248  #define PDECLARE_INSTRUMENTED_MUTEX(var, name, ...) \
249  struct PInstrumentedMutex_##name : PInstrumentedMutex { \
250  PInstrumentedMutex_##name(const char * mutexName = #name) \
251  : PInstrumentedMutex(mutexName, __FILE__, __LINE__, \
252  "Wait " #name, "Held " #name, \
253  __VA_ARGS__) { } \
254  } var
255 
256 #else
257  #define PDECLARE_INSTRUMENTED_MUTEX(var, name, waitTime, heldTime, ...) \
258  PDECLARE_MUTEX(var, name, MinDeadlockTime(waitTime))
259 #endif
260 
261 
270 class PCriticalSection : public PSync
271 {
272  PCLASSINFO(PCriticalSection, PSync);
273 
274  public:
280 
285 
289 
293  PCriticalSection & operator=(const PCriticalSection &) { return *this; }
295 
300  PObject * Clone() const
301  {
302  return new PCriticalSection();
303  }
304 
307  virtual void Wait();
308  inline void Enter() { Wait(); }
309 
315  virtual PBoolean Wait(
316  const PTimeInterval & timeout // Amount of time to wait.
317  );
318 
321  virtual void Signal();
322  inline void Leave() { Signal(); }
323 
327  bool Try();
329 
330 #if _WIN32
331  mutable CRITICAL_SECTION criticalSection;
332 #elif defined(P_PTHREADS) || defined(VX_TASKS)
333  mutable pthread_mutex_t m_mutex;
334 #endif
335 };
336 
337 
338 #endif // PTLIB_MUTEX_H
339 
340 
341 // End Of File ///////////////////////////////////////////////////////////////
void Construct(unsigned timeout)
Information about a source file location.
Definition: object.h:333
unsigned m_excessiveLockTimeout
Definition: mutex.h:45
atomic< bool > m_excessiveLockActive
Definition: mutex.h:46
bool InternalSignal(const PDebugLocation *location)
PObject * Clone() const
Create a new PCriticalSection.
Definition: mutex.h:300
unsigned m_lockCount
Definition: mutex.h:171
void Construct()
PCriticalSection & operator=(const PCriticalSection &)
Assignment operator is allowed but does nothing.
Definition: mutex.h:293
This class defines an arbitrary time interval to millisecond accuracy.
Definition: timeint.h:51
void InternalWait(const PDebugLocation *location)
#define PCLASSINFO(cls, par)
Declare all the standard PTLib class information.
Definition: object.h:2164
const char * m_extra
Definition: object.h:337
bool Try()
Try to enter the critical section for exlusive access.
This class implements critical section mutexes using the most efficient mechanism available on the ho...
Definition: mutex.h:270
PDebugLocation(const char *extra=NULL)
Definition: object.h:339
#define PINLINE
Definition: object.h:194
virtual void ReleasedLock(const PObject &mutex, uint64_t startHeldSamplePoint, bool readOnly, const PDebugLocation &location)
virtual void Signal()
Leave the critical section by unlocking the mutex.
void PlatformSignal(const PDebugLocation *location)
Definition: psync.h:45
PTimedMutex & operator=(const PTimedMutex &)
Assignment operator is allowed but does nothing.
Definition: mutex.h:125
static DeadlockStackWalkModes DeadlockStackWalkMode
Definition: mutex.h:162
void InternalWaitComplete(uint64_t startWaitCycle, const PDebugLocation *location)
PCriticalSection()
Create a new critical section object .
~PCriticalSection()
Destroy the critical section object.
static unsigned ExcessiveLockWaitTime
Definition: mutex.h:154
bool PlatformWait(const PTimeInterval &timeout)
void Enter()
Definition: mutex.h:308
void SetLocationName(const char *name)
Definition: mutex.h:76
bool PBoolean
Definition: object.h:174
This class, along with the PPROFILE_TIMESCOPE() macro, allows the measurement of the time used by a s...
Definition: object.h:1430
void ExcessiveLockPhantom(const PObject &mutex) const
PThreadIdentifier m_lockerId
Definition: mutex.h:168
void Leave()
Definition: mutex.h:322
This class defines a thread mutual exclusion object.
Definition: mutex.h:101
virtual void Signal()
Signal that the synchronisation object is available.
PUniqueThreadIdentifier m_lastUniqueId
Definition: mutex.h:170
Definition: mutex.h:41
uint64_t m_startHeldSamplePoint
Definition: mutex.h:47
virtual void AcquiredLock(uint64_t startWaitCycle, bool readOnly, const PDebugLocation &location)
DeadlockStackWalkModes
Definition: mutex.h:155
virtual void PrintOn(ostream &strm) const
Output the contents of the object to the stream.
PDebugLocation m_location
Definition: mutex.h:44
~PTimedMutex()
Destruction.
virtual ~PMutexExcessiveLockInfo()
Definition: mutex.h:55
Definition: object.h:1537
PThreadIdentifier m_lastLockerId
Definition: mutex.h:169
void PlatformConstruct()
virtual bool InstrumentedWait(const PTimeInterval &timeout, const PDebugLocation &)
As for Wait() but with location of call for instrumentation. Mostly used internally.
Definition: psync.h:66
PINLINE bool Try()
Try to enter the critical section for exlusive access.
Definition: mutex.h:150
virtual void Wait()
Enter the critical section by waiting for exclusive access.
Ultimate parent class for all objects in the class library.
Definition: object.h:2204
void PrintOn(ostream &strm) const
virtual void InstrumentedSignal(const PDebugLocation &)
As for Signal() but with location of call for instrumentation. Mostly used internally.
Definition: psync.h:73
static unsigned MinDeadlockTime(unsigned waitTime)
PTimedMutex PMutex
Definition: mutex.h:189
virtual void Wait()
Block until the synchronisation object is available.