semaphore.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. * Copyright (c) 2012-2018 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/dbartolini/crown/blob/master/LICENSE
  4. */
  5. #include "core/error/error.h"
  6. #include "core/platform.h"
  7. #include "core/thread/semaphore.h"
  8. #if CROWN_PLATFORM_POSIX
  9. #include <pthread.h>
  10. #elif CROWN_PLATFORM_WINDOWS
  11. #include <windows.h>
  12. #include <limits.h> // LONG_MAX
  13. #endif
  14. namespace crown
  15. {
  16. struct Private
  17. {
  18. #if CROWN_PLATFORM_POSIX
  19. pthread_mutex_t mutex;
  20. pthread_cond_t cond;
  21. s32 count;
  22. #elif CROWN_PLATFORM_WINDOWS
  23. HANDLE handle;
  24. #endif
  25. };
  26. Semaphore::Semaphore()
  27. {
  28. CE_STATIC_ASSERT(sizeof(_data) >= sizeof(Private));
  29. Private* priv = (Private*)_data;
  30. #if CROWN_PLATFORM_POSIX
  31. int err = 0;
  32. err = pthread_mutex_init(&priv->mutex, NULL);
  33. CE_ASSERT(err == 0, "pthread_mutex_init: errno = %d", err);
  34. err = pthread_cond_init(&priv->cond, NULL);
  35. CE_ASSERT(err == 0, "pthread_cond_init: errno = %d", err);
  36. CE_UNUSED(err);
  37. priv->count = 0;
  38. #elif CROWN_PLATFORM_WINDOWS
  39. priv->handle = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
  40. CE_ASSERT(priv->handle != NULL, "CreateSemaphore: GetLastError = %d", GetLastError());
  41. CE_UNUSED(priv->handle);
  42. #endif
  43. }
  44. Semaphore::~Semaphore()
  45. {
  46. Private* priv = (Private*)_data;
  47. #if CROWN_PLATFORM_POSIX
  48. int err = pthread_cond_destroy(&priv->cond);
  49. CE_ASSERT(err == 0, "pthread_cond_destroy: errno = %d", err);
  50. CE_UNUSED(err);
  51. #elif CROWN_PLATFORM_WINDOWS
  52. BOOL err = CloseHandle(priv->handle);
  53. CE_ASSERT(err != 0, "CloseHandle: GetLastError = %d", GetLastError());
  54. CE_UNUSED(err);
  55. #endif
  56. }
  57. void Semaphore::post(u32 count)
  58. {
  59. Private* priv = (Private*)_data;
  60. #if CROWN_PLATFORM_POSIX
  61. pthread_mutex_lock(&priv->mutex);
  62. for (u32 i = 0; i < count; ++i)
  63. {
  64. int err = pthread_cond_signal(&priv->cond);
  65. CE_ASSERT(err == 0, "pthread_cond_signal: errno = %d", err);
  66. CE_UNUSED(err);
  67. }
  68. priv->count += count;
  69. pthread_mutex_unlock(&priv->mutex);
  70. #elif CROWN_PLATFORM_WINDOWS
  71. BOOL err = ReleaseSemaphore(priv->handle, count, NULL);
  72. CE_ASSERT(err != 0, "ReleaseSemaphore: GetLastError = %d", GetLastError());
  73. CE_UNUSED(err);
  74. #endif
  75. }
  76. void Semaphore::wait()
  77. {
  78. Private* priv = (Private*)_data;
  79. #if CROWN_PLATFORM_POSIX
  80. pthread_mutex_lock(&priv->mutex);
  81. while (priv->count <= 0)
  82. {
  83. int err = pthread_cond_wait(&priv->cond, &priv->mutex);
  84. CE_ASSERT(err == 0, "pthread_cond_wait: errno = %d", err);
  85. CE_UNUSED(err);
  86. }
  87. priv->count--;
  88. pthread_mutex_unlock(&priv->mutex);
  89. #elif CROWN_PLATFORM_WINDOWS
  90. DWORD err = WaitForSingleObject(priv->handle, INFINITE);
  91. CE_ASSERT(err == WAIT_OBJECT_0, "WaitForSingleObject: GetLastError = %d", GetLastError());
  92. CE_UNUSED(err);
  93. #endif
  94. }
  95. } // namespace crown