Panda3D
 All Classes Functions Variables Enumerations
reMutexDirect.cxx
1 // Filename: reMutexDirect.cxx
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 #include "reMutexDirect.h"
16 #include "thread.h"
17 
18 #ifndef DEBUG_THREADS
19 
20 ////////////////////////////////////////////////////////////////////
21 // Function: ReMutexDirect::output
22 // Access: Published
23 // Description: This method is declared virtual in MutexDebug, but
24 // non-virtual in ReMutexDirect.
25 ////////////////////////////////////////////////////////////////////
26 void ReMutexDirect::
27 output(ostream &out) const {
28  out << "ReMutex " << (void *)this;
29 }
30 
31 #ifndef HAVE_REMUTEXTRUEIMPL
32 ////////////////////////////////////////////////////////////////////
33 // Function: ReMutexDirect::do_acquire
34 // Access: Private
35 // Description: The private implementation of acquire(), for the case in
36 // which the underlying lock system does not provide a
37 // reentrant mutex (and therefore we have to build this
38 // functionality on top of the existing non-reentrant
39 // mutex).
40 ////////////////////////////////////////////////////////////////////
41 void ReMutexDirect::
42 do_acquire(Thread *current_thread) {
43  _lock_impl.acquire();
44 
45  if (_locking_thread == (Thread *)NULL) {
46  // The mutex is not already locked by anyone. Lock it.
47  _locking_thread = current_thread;
48  ++_lock_count;
49  nassertd(_lock_count == 1) {
50  }
51 
52  } else if (_locking_thread == current_thread) {
53  // The mutex is already locked by this thread. Increment the lock
54  // count.
55  ++_lock_count;
56  nassertd(_lock_count > 0) {
57  }
58 
59  } else {
60  // The mutex is locked by some other thread. Go to sleep on the
61  // condition variable until it's unlocked.
62  while (_locking_thread != (Thread *)NULL) {
63  _cvar_impl.wait();
64  }
65 
66  _locking_thread = current_thread;
67  ++_lock_count;
68  nassertd(_lock_count == 1) {
69  }
70  }
71  _lock_impl.release();
72 }
73 #endif // !HAVE_REMUTEXTRUEIMPL
74 
75 #ifndef HAVE_REMUTEXTRUEIMPL
76 ////////////////////////////////////////////////////////////////////
77 // Function: ReMutexDirect::do_try_acquire
78 // Access: Private
79 // Description: The private implementation of acquire(false), for the
80 // case in which the underlying lock system does not
81 // provide a reentrant mutex (and therefore we have to
82 // build this functionality on top of the existing
83 // non-reentrant mutex).
84 ////////////////////////////////////////////////////////////////////
85 bool ReMutexDirect::
86 do_try_acquire(Thread *current_thread) {
87  bool acquired = true;
88  _lock_impl.acquire();
89 
90  if (_locking_thread == (Thread *)NULL) {
91  // The mutex is not already locked by anyone. Lock it.
92  _locking_thread = current_thread;
93  ++_lock_count;
94  nassertd(_lock_count == 1) {
95  }
96 
97  } else if (_locking_thread == current_thread) {
98  // The mutex is already locked by this thread. Increment the lock
99  // count.
100  ++_lock_count;
101  nassertd(_lock_count > 0) {
102  }
103 
104  } else {
105  // The mutex is locked by some other thread. Return false.
106  acquired = false;
107  }
108  _lock_impl.release();
109 
110  return acquired;
111 }
112 #endif // !HAVE_REMUTEXTRUEIMPL
113 
114 #ifndef HAVE_REMUTEXTRUEIMPL
115 ////////////////////////////////////////////////////////////////////
116 // Function: ReMutexDirect::do_elevate_lock
117 // Access: Private
118 // Description: The private implementation of acquire(), for the case in
119 // which the underlying lock system does not provide a
120 // reentrant mutex (and therefore we have to build this
121 // functionality on top of the existing non-reentrant
122 // mutex).
123 ////////////////////////////////////////////////////////////////////
124 void ReMutexDirect::
125 do_elevate_lock() {
126  _lock_impl.acquire();
127 
128 #ifdef _DEBUG
129  nassertd(_locking_thread == Thread::get_current_thread()) {
130  _lock_impl.release();
131  return;
132  }
133 #elif !defined(NDEBUG)
134  nassertd(_locking_thread != (Thread *)NULL) {
135  _lock_impl.release();
136  return;
137  }
138 #endif // NDEBUG
139 
140  // We know the mutex is already locked by this thread. Increment
141  // the lock count.
142  ++_lock_count;
143  nassertd(_lock_count > 0) {
144  }
145 
146  _lock_impl.release();
147 }
148 #endif // !HAVE_REMUTEXTRUEIMPL
149 
150 #ifndef HAVE_REMUTEXTRUEIMPL
151 ////////////////////////////////////////////////////////////////////
152 // Function: ReMutexDirect::do_release
153 // Access: Private
154 // Description: The private implementation of release(), for the case
155 // in which the underlying lock system does not provide
156 // a reentrant mutex (and therefore we have to build
157 // this functionality on top of the existing
158 // non-reentrant mutex).
159 ////////////////////////////////////////////////////////////////////
160 void ReMutexDirect::
161 do_release() {
162  _lock_impl.acquire();
163 
164 #ifdef _DEBUG
165  if (_locking_thread != Thread::get_current_thread()) {
166  ostringstream ostr;
167  ostr << *_locking_thread << " attempted to release "
168  << *this << " which it does not own";
169  nassert_raise(ostr.str());
170  _lock_impl.release();
171  return;
172  }
173 #endif // _DEBUG
174 
175  nassertd(_lock_count > 0) {
176  }
177 
178  --_lock_count;
179  if (_lock_count == 0) {
180  // That was the last lock held by this thread. Release the lock.
181  _locking_thread = (Thread *)NULL;
182  _cvar_impl.notify();
183  }
184  _lock_impl.release();
185 }
186 #endif // !HAVE_REMUTEXTRUEIMPL
187 
188 #endif // !DEBUG_THREADS
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
void output(ostream &out) const
This method is declared virtual in MutexDebug, but non-virtual in ReMutexDirect.
A thread; that is, a lightweight process.
Definition: thread.h:51