IlmThreadSemaphorePosixCompat.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
  4. // Digital Ltd. LLC
  5. //
  6. // All rights reserved.
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are
  10. // met:
  11. // * Redistributions of source code must retain the above copyright
  12. // notice, this list of conditions and the following disclaimer.
  13. // * Redistributions in binary form must reproduce the above
  14. // copyright notice, this list of conditions and the following disclaimer
  15. // in the documentation and/or other materials provided with the
  16. // distribution.
  17. // * Neither the name of Industrial Light & Magic nor the names of
  18. // its contributors may be used to endorse or promote products derived
  19. // from this software without specific prior written permission.
  20. //
  21. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. //
  33. ///////////////////////////////////////////////////////////////////////////
  34. //-----------------------------------------------------------------------------
  35. //
  36. // class Semaphore -- implementation for for platforms that do
  37. // support Posix threads but do not support Posix semaphores,
  38. // for example, OS X
  39. //
  40. //-----------------------------------------------------------------------------
  41. #include "IlmBaseConfig.h"
  42. #if (!HAVE_POSIX_SEMAPHORES) && !defined (_WIN32) && ! defined (_WIN64)
  43. #include "IlmThreadSemaphore.h"
  44. #include "Iex.h"
  45. #include <assert.h>
  46. ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
  47. #if ILMBASE_FORCE_CXX03 && HAVE_PTHREAD
  48. Semaphore::Semaphore (unsigned int value)
  49. {
  50. if (int error = ::pthread_mutex_init (&_semaphore.mutex, 0))
  51. IEX_NAMESPACE::throwErrnoExc ("Cannot initialize mutex (%T).", error);
  52. if (int error = ::pthread_cond_init (&_semaphore.nonZero, 0))
  53. IEX_NAMESPACE::throwErrnoExc ("Cannot initialize condition variable (%T).",
  54. error);
  55. _semaphore.count = value;
  56. _semaphore.numWaiting = 0;
  57. }
  58. Semaphore::~Semaphore ()
  59. {
  60. int error = ::pthread_cond_destroy (&_semaphore.nonZero);
  61. assert (error == 0);
  62. error = ::pthread_mutex_destroy (&_semaphore.mutex);
  63. assert (error == 0);
  64. }
  65. void
  66. Semaphore::wait ()
  67. {
  68. ::pthread_mutex_lock (&_semaphore.mutex);
  69. _semaphore.numWaiting++;
  70. while (_semaphore.count == 0)
  71. {
  72. if (int error = ::pthread_cond_wait (&_semaphore.nonZero,
  73. &_semaphore.mutex))
  74. {
  75. ::pthread_mutex_unlock (&_semaphore.mutex);
  76. IEX_NAMESPACE::throwErrnoExc ("Cannot wait on condition variable (%T).",
  77. error);
  78. }
  79. }
  80. _semaphore.numWaiting--;
  81. _semaphore.count--;
  82. ::pthread_mutex_unlock (&_semaphore.mutex);
  83. }
  84. bool
  85. Semaphore::tryWait ()
  86. {
  87. ::pthread_mutex_lock (&_semaphore.mutex);
  88. if (_semaphore.count == 0)
  89. {
  90. ::pthread_mutex_unlock (&_semaphore.mutex);
  91. return false;
  92. }
  93. else
  94. {
  95. _semaphore.count--;
  96. ::pthread_mutex_unlock (&_semaphore.mutex);
  97. return true;
  98. }
  99. }
  100. void
  101. Semaphore::post ()
  102. {
  103. ::pthread_mutex_lock (&_semaphore.mutex);
  104. if (_semaphore.numWaiting > 0)
  105. {
  106. int error;
  107. if (_semaphore.numWaiting > 1 && _semaphore.count > 1)
  108. {
  109. error = ::pthread_cond_broadcast (&_semaphore.nonZero);
  110. }
  111. else
  112. {
  113. error = ::pthread_cond_signal (&_semaphore.nonZero);
  114. }
  115. if (error)
  116. {
  117. ::pthread_mutex_unlock (&_semaphore.mutex);
  118. IEX_NAMESPACE::throwErrnoExc ("Cannot signal condition variable (%T).",
  119. error);
  120. }
  121. }
  122. _semaphore.count++;
  123. ::pthread_mutex_unlock (&_semaphore.mutex);
  124. }
  125. int
  126. Semaphore::value () const
  127. {
  128. ::pthread_mutex_lock (&_semaphore.mutex);
  129. int value = _semaphore.count;
  130. ::pthread_mutex_unlock (&_semaphore.mutex);
  131. return value;
  132. }
  133. #else
  134. Semaphore::Semaphore (unsigned int value)
  135. {
  136. _semaphore.count = value;
  137. _semaphore.numWaiting = 0;
  138. }
  139. Semaphore::~Semaphore ()
  140. {
  141. }
  142. void
  143. Semaphore::wait ()
  144. {
  145. std::unique_lock<std::mutex> lk(_semaphore.mutex);
  146. _semaphore.numWaiting++;
  147. while (_semaphore.count == 0)
  148. _semaphore.nonZero.wait (lk);
  149. _semaphore.numWaiting--;
  150. _semaphore.count--;
  151. }
  152. bool
  153. Semaphore::tryWait ()
  154. {
  155. std::lock_guard<std::mutex> lk(_semaphore.mutex);
  156. if (_semaphore.count == 0)
  157. return false;
  158. _semaphore.count--;
  159. return true;
  160. }
  161. void
  162. Semaphore::post ()
  163. {
  164. std::lock_guard<std::mutex> lk(_semaphore.mutex);
  165. _semaphore.count++;
  166. if (_semaphore.numWaiting > 0)
  167. {
  168. if (_semaphore.count > 1)
  169. _semaphore.nonZero.notify_all();
  170. else
  171. _semaphore.nonZero.notify_one();
  172. }
  173. }
  174. int
  175. Semaphore::value () const
  176. {
  177. std::lock_guard<std::mutex> lk(_semaphore.mutex);
  178. return _semaphore.count;
  179. }
  180. #endif
  181. ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
  182. #endif