condition.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #include "condition.h"
  17. #if defined(__WIN32__) && !defined(PTHREADS_WIN32)
  18. #define WIN32_LEAN_AND_MEAN
  19. #include <windows.h>
  20. namespace embree
  21. {
  22. #if (_WIN32_WINNT >= 0x0600)
  23. struct ConditionImplementation
  24. {
  25. __forceinline ConditionImplementation () {
  26. InitializeConditionVariable(&cond);
  27. }
  28. __forceinline ~ConditionImplementation () {
  29. }
  30. __forceinline void wait(MutexSys& mutex_in) {
  31. SleepConditionVariableCS(&cond, (LPCRITICAL_SECTION)mutex_in.mutex, INFINITE);
  32. }
  33. __forceinline void notify_all() {
  34. WakeAllConditionVariable(&cond);
  35. }
  36. public:
  37. CONDITION_VARIABLE cond;
  38. };
  39. #else
  40. #pragma message ("WARNING: This condition variable implementation has known performance issues!")
  41. struct ConditionImplementation
  42. {
  43. __forceinline ConditionImplementation () : count(0) {
  44. event = CreateEvent(nullptr,TRUE,FALSE,nullptr);
  45. }
  46. __forceinline ~ConditionImplementation () {
  47. CloseHandle(event);
  48. }
  49. __forceinline void wait(MutexSys& mutex_in)
  50. {
  51. /* atomically increment thread count */
  52. ssize_t cnt0 = atomic_add(&count,+1);
  53. mutex_in.unlock();
  54. /* all threads except the last one are wait in the barrier */
  55. if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
  56. THROW_RUNTIME_ERROR("WaitForSingleObject failed");
  57. /* atomically decrement thread count */
  58. mutex_in.lock();
  59. ssize_t cnt1 = atomic_add(&count,-1);
  60. /* the last thread that left the barrier resets the event again */
  61. if (cnt1 == 1) {
  62. if (ResetEvent(event) == 0)
  63. THROW_RUNTIME_ERROR("ResetEvent failed");
  64. }
  65. }
  66. __forceinline void notify_all()
  67. {
  68. /* we support only one broadcast at a given time */
  69. bool hasWaiters = count > 0;
  70. /* if threads are waiting, let them continue */
  71. if (hasWaiters)
  72. if (SetEvent(event) == 0)
  73. THROW_RUNTIME_ERROR("SetEvent failed");
  74. }
  75. public:
  76. HANDLE event;
  77. volatile atomic_t count;
  78. };
  79. #endif
  80. }
  81. #endif
  82. #if defined(__UNIX__) || defined(PTHREADS_WIN32)
  83. #include <pthread.h>
  84. namespace embree
  85. {
  86. struct ConditionImplementation
  87. {
  88. __forceinline ConditionImplementation () {
  89. pthread_cond_init(&cond,nullptr);
  90. }
  91. __forceinline ~ConditionImplementation() {
  92. pthread_cond_destroy(&cond);
  93. }
  94. __forceinline void wait(MutexSys& mutex) {
  95. pthread_cond_wait(&cond, (pthread_mutex_t*)mutex.mutex);
  96. }
  97. __forceinline void notify_all() {
  98. pthread_cond_broadcast(&cond);
  99. }
  100. public:
  101. pthread_cond_t cond;
  102. };
  103. }
  104. #endif
  105. namespace embree
  106. {
  107. ConditionSys::ConditionSys () {
  108. cond = new ConditionImplementation;
  109. }
  110. ConditionSys::~ConditionSys() {
  111. delete (ConditionImplementation*) cond;
  112. }
  113. void ConditionSys::wait(MutexSys& mutex) {
  114. ((ConditionImplementation*) cond)->wait(mutex);
  115. }
  116. void ConditionSys::notify_all() {
  117. ((ConditionImplementation*) cond)->notify_all();
  118. }
  119. }