Panda3D
mutexDebug.I
1 // Filename: mutexDebug.I
2 // Created by: drose (13Feb06)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 
16 ////////////////////////////////////////////////////////////////////
17 // Function: MutexDebug::Copy Constructor
18 // Access: Private
19 // Description: Do not attempt to copy mutexes.
20 ////////////////////////////////////////////////////////////////////
21 INLINE MutexDebug::
22 MutexDebug(const MutexDebug &copy) : _cvar_impl(*get_global_lock()) {
23  nassertv(false);
24 }
25 
26 ////////////////////////////////////////////////////////////////////
27 // Function: MutexDebug::Copy Assignment Operator
28 // Access: Private
29 // Description: Do not attempt to copy mutexes.
30 ////////////////////////////////////////////////////////////////////
31 INLINE void MutexDebug::
32 operator = (const MutexDebug &copy) {
33  nassertv(false);
34 }
35 
36 ////////////////////////////////////////////////////////////////////
37 // Function: MutexDebug::acquire
38 // Access: Published
39 // Description: Grabs the mutex if it is available. If it is not
40 // available, blocks until it becomes available, then
41 // grabs it. In either case, the function does not
42 // return until the mutex is held; you should then call
43 // unlock().
44 //
45 // This method is considered const so that you can lock
46 // and unlock const mutexes, mainly to allow thread-safe
47 // access to otherwise const data.
48 //
49 // Also see MutexHolder.
50 ////////////////////////////////////////////////////////////////////
51 INLINE void MutexDebug::
52 acquire(Thread *current_thread) const {
53  TAU_PROFILE("void MutexDebug::acquire(Thread *)", " ", TAU_USER);
54  nassertv(current_thread == Thread::get_current_thread());
55  _global_lock->acquire();
56  ((MutexDebug *)this)->do_acquire(current_thread);
57  _global_lock->release();
58 }
59 
60 ////////////////////////////////////////////////////////////////////
61 // Function: MutexDebug::try_acquire
62 // Access: Published
63 // Description: Returns immediately, with a true value indicating the
64 // mutex has been acquired, and false indicating it has
65 // not.
66 ////////////////////////////////////////////////////////////////////
67 INLINE bool MutexDebug::
68 try_acquire(Thread *current_thread) const {
69  TAU_PROFILE("void MutexDebug::acquire(Thread *)", " ", TAU_USER);
70  nassertr(current_thread == Thread::get_current_thread(), false);
71  _global_lock->acquire();
72  bool acquired = ((MutexDebug *)this)->do_try_acquire(current_thread);
73  _global_lock->release();
74  return acquired;
75 }
76 
77 ////////////////////////////////////////////////////////////////////
78 // Function: MutexDebug::elevate_lock
79 // Access: Published
80 // Description: This method increments the lock count, assuming the
81 // calling thread already holds the lock. After this
82 // call, release() will need to be called one additional
83 // time to release the lock.
84 //
85 // This method really performs the same function as
86 // acquire(), but it offers a potential (slight)
87 // performance benefit when the calling thread knows
88 // that it already holds the lock. It is an error to
89 // call this when the calling thread does not hold the
90 // lock.
91 ////////////////////////////////////////////////////////////////////
92 INLINE void MutexDebug::
93 elevate_lock() const {
94  TAU_PROFILE("void MutexDebug::elevate_lock()", " ", TAU_USER);
95  // You may only pass call elevate_lock() on a ReMutex--that is, to a
96  // mutex whose _allow_recursion flag is true.
97  nassertv(_allow_recursion);
98 
99  // Also, it's an error to call this if the lock is not already held.
100  nassertv(debug_is_locked());
101 
102  acquire();
103 }
104 
105 ////////////////////////////////////////////////////////////////////
106 // Function: MutexDebug::release
107 // Access: Published
108 // Description: Releases the mutex. It is an error to call this if
109 // the mutex was not already locked.
110 //
111 // This method is considered const so that you can lock
112 // and unlock const mutexes, mainly to allow thread-safe
113 // access to otherwise const data.
114 ////////////////////////////////////////////////////////////////////
115 INLINE void MutexDebug::
116 release() const {
117  TAU_PROFILE("void MutexDebug::release()", " ", TAU_USER);
118  _global_lock->acquire();
119  ((MutexDebug *)this)->do_release();
120  _global_lock->release();
121 }
122 
123 ////////////////////////////////////////////////////////////////////
124 // Function: MutexDebug::debug_is_locked
125 // Access: Published
126 // Description: Returns true if the current thread has locked the
127 // Mutex, false otherwise. This method is only intended
128 // for use in debugging, hence the method name; in the
129 // MutexDebug case, it always returns true, since
130 // there's not a reliable way to determine this
131 // otherwise.
132 ////////////////////////////////////////////////////////////////////
133 INLINE bool MutexDebug::
134 debug_is_locked() const {
135  TAU_PROFILE("bool MutexDebug::debug_is_locked()", " ", TAU_USER);
136  _global_lock->acquire();
137  bool is_locked = do_debug_is_locked();
138  _global_lock->release();
139  return is_locked;
140 }
141 
142 ////////////////////////////////////////////////////////////////////
143 // Function: MutexDebug::get_global_lock
144 // Access: Private, Static
145 // Description: Ensures the global MutexImpl pointer has been
146 // created, and returns its pointer. Since this method
147 // is called by the MutexDebug constructor, any other
148 // (non-static) methods of MutexDebug may simply assume
149 // that the pointer has already been created.
150 ////////////////////////////////////////////////////////////////////
151 INLINE MutexTrueImpl *MutexDebug::
152 get_global_lock() {
153  if (_global_lock == (MutexTrueImpl *)NULL) {
154  _global_lock = new MutexTrueImpl;
155  }
156  return _global_lock;
157 }
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
A thread; that is, a lightweight process.
Definition: thread.h:51
A fake mutex implementation for single-threaded applications that don't need any synchronization cont...