Panda3D
|
00001 // Filename: reMutexDirect.cxx 00002 // Created by: drose (13Feb06) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "reMutexDirect.h" 00016 #include "thread.h" 00017 00018 #ifndef DEBUG_THREADS 00019 00020 //////////////////////////////////////////////////////////////////// 00021 // Function: ReMutexDirect::output 00022 // Access: Published 00023 // Description: This method is declared virtual in MutexDebug, but 00024 // non-virtual in ReMutexDirect. 00025 //////////////////////////////////////////////////////////////////// 00026 void ReMutexDirect:: 00027 output(ostream &out) const { 00028 out << "ReMutex " << (void *)this; 00029 } 00030 00031 #ifndef HAVE_REMUTEXTRUEIMPL 00032 //////////////////////////////////////////////////////////////////// 00033 // Function: ReMutexDirect::do_acquire 00034 // Access: Private 00035 // Description: The private implementation of acquire(), for the case in 00036 // which the underlying lock system does not provide a 00037 // reentrant mutex (and therefore we have to build this 00038 // functionality on top of the existing non-reentrant 00039 // mutex). 00040 //////////////////////////////////////////////////////////////////// 00041 void ReMutexDirect:: 00042 do_acquire(Thread *current_thread) { 00043 _lock_impl.acquire(); 00044 00045 if (_locking_thread == (Thread *)NULL) { 00046 // The mutex is not already locked by anyone. Lock it. 00047 _locking_thread = current_thread; 00048 ++_lock_count; 00049 nassertd(_lock_count == 1) { 00050 } 00051 00052 } else if (_locking_thread == current_thread) { 00053 // The mutex is already locked by this thread. Increment the lock 00054 // count. 00055 ++_lock_count; 00056 nassertd(_lock_count > 0) { 00057 } 00058 00059 } else { 00060 // The mutex is locked by some other thread. Go to sleep on the 00061 // condition variable until it's unlocked. 00062 while (_locking_thread != (Thread *)NULL) { 00063 _cvar_impl.wait(); 00064 } 00065 00066 _locking_thread = current_thread; 00067 ++_lock_count; 00068 nassertd(_lock_count == 1) { 00069 } 00070 } 00071 _lock_impl.release(); 00072 } 00073 #endif // !HAVE_REMUTEXTRUEIMPL 00074 00075 #ifndef HAVE_REMUTEXTRUEIMPL 00076 //////////////////////////////////////////////////////////////////// 00077 // Function: ReMutexDirect::do_try_acquire 00078 // Access: Private 00079 // Description: The private implementation of acquire(false), for the 00080 // case in which the underlying lock system does not 00081 // provide a reentrant mutex (and therefore we have to 00082 // build this functionality on top of the existing 00083 // non-reentrant mutex). 00084 //////////////////////////////////////////////////////////////////// 00085 bool ReMutexDirect:: 00086 do_try_acquire(Thread *current_thread) { 00087 bool acquired = true; 00088 _lock_impl.acquire(); 00089 00090 if (_locking_thread == (Thread *)NULL) { 00091 // The mutex is not already locked by anyone. Lock it. 00092 _locking_thread = current_thread; 00093 ++_lock_count; 00094 nassertd(_lock_count == 1) { 00095 } 00096 00097 } else if (_locking_thread == current_thread) { 00098 // The mutex is already locked by this thread. Increment the lock 00099 // count. 00100 ++_lock_count; 00101 nassertd(_lock_count > 0) { 00102 } 00103 00104 } else { 00105 // The mutex is locked by some other thread. Return false. 00106 acquired = false; 00107 } 00108 _lock_impl.release(); 00109 00110 return acquired; 00111 } 00112 #endif // !HAVE_REMUTEXTRUEIMPL 00113 00114 #ifndef HAVE_REMUTEXTRUEIMPL 00115 //////////////////////////////////////////////////////////////////// 00116 // Function: ReMutexDirect::do_elevate_lock 00117 // Access: Private 00118 // Description: The private implementation of acquire(), for the case in 00119 // which the underlying lock system does not provide a 00120 // reentrant mutex (and therefore we have to build this 00121 // functionality on top of the existing non-reentrant 00122 // mutex). 00123 //////////////////////////////////////////////////////////////////// 00124 void ReMutexDirect:: 00125 do_elevate_lock() { 00126 _lock_impl.acquire(); 00127 00128 #ifdef _DEBUG 00129 nassertd(_locking_thread == Thread::get_current_thread()) { 00130 _lock_impl.release(); 00131 return; 00132 } 00133 #elif !defined(NDEBUG) 00134 nassertd(_locking_thread != (Thread *)NULL) { 00135 _lock_impl.release(); 00136 return; 00137 } 00138 #endif // NDEBUG 00139 00140 // We know the mutex is already locked by this thread. Increment 00141 // the lock count. 00142 ++_lock_count; 00143 nassertd(_lock_count > 0) { 00144 } 00145 00146 _lock_impl.release(); 00147 } 00148 #endif // !HAVE_REMUTEXTRUEIMPL 00149 00150 #ifndef HAVE_REMUTEXTRUEIMPL 00151 //////////////////////////////////////////////////////////////////// 00152 // Function: ReMutexDirect::do_release 00153 // Access: Private 00154 // Description: The private implementation of release(), for the case 00155 // in which the underlying lock system does not provide 00156 // a reentrant mutex (and therefore we have to build 00157 // this functionality on top of the existing 00158 // non-reentrant mutex). 00159 //////////////////////////////////////////////////////////////////// 00160 void ReMutexDirect:: 00161 do_release() { 00162 _lock_impl.acquire(); 00163 00164 #ifdef _DEBUG 00165 if (_locking_thread != Thread::get_current_thread()) { 00166 ostringstream ostr; 00167 ostr << *_locking_thread << " attempted to release " 00168 << *this << " which it does not own"; 00169 nassert_raise(ostr.str()); 00170 _lock_impl.release(); 00171 return; 00172 } 00173 #endif // _DEBUG 00174 00175 nassertd(_lock_count > 0) { 00176 } 00177 00178 --_lock_count; 00179 if (_lock_count == 0) { 00180 // That was the last lock held by this thread. Release the lock. 00181 _locking_thread = (Thread *)NULL; 00182 _cvar_impl.notify(); 00183 } 00184 _lock_impl.release(); 00185 } 00186 #endif // !HAVE_REMUTEXTRUEIMPL 00187 00188 #endif // !DEBUG_THREADS