reMutexDirect.cxx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. #include "reMutexDirect.h"
  14. #include "thread.h"
  15. #ifndef DEBUG_THREADS
  16. /**
  17. * This method is declared virtual in MutexDebug, but non-virtual in
  18. * ReMutexDirect.
  19. */
  20. void ReMutexDirect::
  21. output(std::ostream &out) const {
  22. out << "ReMutex " << (void *)this;
  23. }
  24. #ifndef HAVE_REMUTEXTRUEIMPL
  25. /**
  26. * The private implementation of acquire(), for the case in which the
  27. * underlying lock system does not provide a reentrant mutex (and therefore we
  28. * have to build this functionality on top of the existing non-reentrant
  29. * mutex).
  30. */
  31. void ReMutexDirect::
  32. do_lock(Thread *current_thread) {
  33. _lock_impl.lock();
  34. if (_locking_thread == nullptr) {
  35. // The mutex is not already locked by anyone. Lock it.
  36. _locking_thread = current_thread;
  37. ++_lock_count;
  38. nassertd(_lock_count == 1) {
  39. }
  40. } else if (_locking_thread == current_thread) {
  41. // The mutex is already locked by this thread. Increment the lock count.
  42. ++_lock_count;
  43. nassertd(_lock_count > 0) {
  44. }
  45. } else {
  46. // The mutex is locked by some other thread. Go to sleep on the condition
  47. // variable until it's unlocked.
  48. while (_locking_thread != nullptr) {
  49. _cvar_impl.wait();
  50. }
  51. _locking_thread = current_thread;
  52. ++_lock_count;
  53. nassertd(_lock_count == 1) {
  54. }
  55. }
  56. _lock_impl.unlock();
  57. }
  58. #endif // !HAVE_REMUTEXTRUEIMPL
  59. #ifndef HAVE_REMUTEXTRUEIMPL
  60. /**
  61. * The private implementation of acquire(false), for the case in which the
  62. * underlying lock system does not provide a reentrant mutex (and therefore we
  63. * have to build this functionality on top of the existing non-reentrant
  64. * mutex).
  65. */
  66. bool ReMutexDirect::
  67. do_try_lock(Thread *current_thread) {
  68. bool acquired = true;
  69. _lock_impl.lock();
  70. if (_locking_thread == nullptr) {
  71. // The mutex is not already locked by anyone. Lock it.
  72. _locking_thread = current_thread;
  73. ++_lock_count;
  74. nassertd(_lock_count == 1) {
  75. }
  76. } else if (_locking_thread == current_thread) {
  77. // The mutex is already locked by this thread. Increment the lock count.
  78. ++_lock_count;
  79. nassertd(_lock_count > 0) {
  80. }
  81. } else {
  82. // The mutex is locked by some other thread. Return false.
  83. acquired = false;
  84. }
  85. _lock_impl.unlock();
  86. return acquired;
  87. }
  88. #endif // !HAVE_REMUTEXTRUEIMPL
  89. #ifndef HAVE_REMUTEXTRUEIMPL
  90. /**
  91. * The private implementation of acquire(), for the case in which the
  92. * underlying lock system does not provide a reentrant mutex (and therefore we
  93. * have to build this functionality on top of the existing non-reentrant
  94. * mutex).
  95. */
  96. void ReMutexDirect::
  97. do_elevate_lock() {
  98. _lock_impl.lock();
  99. #ifdef _DEBUG
  100. nassertd(_locking_thread == Thread::get_current_thread()) {
  101. _lock_impl.unlock();
  102. return;
  103. }
  104. #elif !defined(NDEBUG)
  105. nassertd(_locking_thread != nullptr) {
  106. _lock_impl.unlock();
  107. return;
  108. }
  109. #endif // NDEBUG
  110. // We know the mutex is already locked by this thread. Increment the lock
  111. // count.
  112. ++_lock_count;
  113. nassertd(_lock_count > 0) {
  114. }
  115. _lock_impl.unlock();
  116. }
  117. #endif // !HAVE_REMUTEXTRUEIMPL
  118. #ifndef HAVE_REMUTEXTRUEIMPL
  119. /**
  120. * The private implementation of release(), for the case in which the
  121. * underlying lock system does not provide a reentrant mutex (and therefore we
  122. * have to build this functionality on top of the existing non-reentrant
  123. * mutex).
  124. */
  125. void ReMutexDirect::
  126. do_unlock(Thread *current_thread) {
  127. _lock_impl.lock();
  128. #ifdef _DEBUG
  129. if (_locking_thread != current_thread) {
  130. std::ostringstream ostr;
  131. ostr << *_locking_thread << " attempted to release "
  132. << *this << " which it does not own";
  133. nassert_raise(ostr.str());
  134. _lock_impl.unlock();
  135. return;
  136. }
  137. #endif // _DEBUG
  138. nassertd(_lock_count > 0) {
  139. }
  140. --_lock_count;
  141. if (_lock_count == 0) {
  142. // That was the last lock held by this thread. Release the lock.
  143. _locking_thread = nullptr;
  144. _cvar_impl.notify();
  145. }
  146. _lock_impl.unlock();
  147. }
  148. #endif // !HAVE_REMUTEXTRUEIMPL
  149. #endif // !DEBUG_THREADS