Panda3D
reMutexDirect.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file reMutexDirect.cxx
10  * @author drose
11  * @date 2006-02-13
12  */
13 
14 #include "reMutexDirect.h"
15 #include "thread.h"
16 
17 #ifndef DEBUG_THREADS
18 
19 /**
20  * This method is declared virtual in MutexDebug, but non-virtual in
21  * ReMutexDirect.
22  */
23 void ReMutexDirect::
24 output(std::ostream &out) const {
25  out << "ReMutex " << (void *)this;
26 }
27 
28 #ifndef HAVE_REMUTEXTRUEIMPL
29 /**
30  * The private implementation of acquire(), for the case in which the
31  * underlying lock system does not provide a reentrant mutex (and therefore we
32  * have to build this functionality on top of the existing non-reentrant
33  * mutex).
34  */
35 void ReMutexDirect::
36 do_lock(Thread *current_thread) {
37  _lock_impl.lock();
38 
39  if (_locking_thread == nullptr) {
40  // The mutex is not already locked by anyone. Lock it.
41  _locking_thread = current_thread;
42  ++_lock_count;
43  nassertd(_lock_count == 1) {
44  }
45 
46  } else if (_locking_thread == current_thread) {
47  // The mutex is already locked by this thread. Increment the lock count.
48  ++_lock_count;
49  nassertd(_lock_count > 0) {
50  }
51 
52  } else {
53  // The mutex is locked by some other thread. Go to sleep on the condition
54  // variable until it's unlocked.
55  while (_locking_thread != nullptr) {
56  _cvar_impl.wait();
57  }
58 
59  _locking_thread = current_thread;
60  ++_lock_count;
61  nassertd(_lock_count == 1) {
62  }
63  }
64  _lock_impl.unlock();
65 }
66 #endif // !HAVE_REMUTEXTRUEIMPL
67 
68 #ifndef HAVE_REMUTEXTRUEIMPL
69 /**
70  * The private implementation of acquire(false), for the case in which the
71  * underlying lock system does not provide a reentrant mutex (and therefore we
72  * have to build this functionality on top of the existing non-reentrant
73  * mutex).
74  */
75 bool ReMutexDirect::
76 do_try_lock(Thread *current_thread) {
77  bool acquired = true;
78  _lock_impl.lock();
79 
80  if (_locking_thread == nullptr) {
81  // The mutex is not already locked by anyone. Lock it.
82  _locking_thread = current_thread;
83  ++_lock_count;
84  nassertd(_lock_count == 1) {
85  }
86 
87  } else if (_locking_thread == current_thread) {
88  // The mutex is already locked by this thread. Increment the lock count.
89  ++_lock_count;
90  nassertd(_lock_count > 0) {
91  }
92 
93  } else {
94  // The mutex is locked by some other thread. Return false.
95  acquired = false;
96  }
97  _lock_impl.unlock();
98 
99  return acquired;
100 }
101 #endif // !HAVE_REMUTEXTRUEIMPL
102 
103 #ifndef HAVE_REMUTEXTRUEIMPL
104 /**
105  * The private implementation of acquire(), for the case in which the
106  * underlying lock system does not provide a reentrant mutex (and therefore we
107  * have to build this functionality on top of the existing non-reentrant
108  * mutex).
109  */
110 void ReMutexDirect::
111 do_elevate_lock() {
112  _lock_impl.lock();
113 
114 #ifdef _DEBUG
115  nassertd(_locking_thread == Thread::get_current_thread()) {
116  _lock_impl.unlock();
117  return;
118  }
119 #elif !defined(NDEBUG)
120  nassertd(_locking_thread != nullptr) {
121  _lock_impl.unlock();
122  return;
123  }
124 #endif // NDEBUG
125 
126  // We know the mutex is already locked by this thread. Increment the lock
127  // count.
128  ++_lock_count;
129  nassertd(_lock_count > 0) {
130  }
131 
132  _lock_impl.unlock();
133 }
134 #endif // !HAVE_REMUTEXTRUEIMPL
135 
136 #ifndef HAVE_REMUTEXTRUEIMPL
137 /**
138  * The private implementation of release(), for the case in which the
139  * underlying lock system does not provide a reentrant mutex (and therefore we
140  * have to build this functionality on top of the existing non-reentrant
141  * mutex).
142  */
143 void ReMutexDirect::
144 do_unlock(Thread *current_thread) {
145  _lock_impl.lock();
146 
147 #ifdef _DEBUG
148  if (_locking_thread != current_thread) {
149  std::ostringstream ostr;
150  ostr << *_locking_thread << " attempted to release "
151  << *this << " which it does not own";
152  nassert_raise(ostr.str());
153  _lock_impl.unlock();
154  return;
155  }
156 #endif // _DEBUG
157 
158  nassertd(_lock_count > 0) {
159  }
160 
161  --_lock_count;
162  if (_lock_count == 0) {
163  // That was the last lock held by this thread. Release the lock.
164  _locking_thread = nullptr;
165  _cvar_impl.notify();
166  }
167  _lock_impl.unlock();
168 }
169 #endif // !HAVE_REMUTEXTRUEIMPL
170 
171 #endif // !DEBUG_THREADS
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A thread; that is, a lightweight process.
Definition: thread.h:46
void output(std::ostream &out) const
This method is declared virtual in MutexDebug, but non-virtual in ReMutexDirect.