PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/mordor/semaphore.cpp

http://github.com/mozy/mordor
C++ | 129 lines | 117 code | 11 blank | 1 comment | 23 complexity | 7e82c54c54c3f40e27bb04af468a9dd7 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Copyright (c) 2009 - Mozy, Inc.
  2. #include "semaphore.h"
  3. #include "assert.h"
  4. #include "exception.h"
  5. #ifndef WINDOWS
  6. #include <errno.h>
  7. #endif
  8. #ifdef FREEBSD
  9. #include <sys/sem.h>
  10. #endif
  11. #ifdef OSX
  12. #include <mach/mach_init.h>
  13. #include <mach/task.h>
  14. #endif
  15. namespace Mordor {
  16. Semaphore::Semaphore(unsigned int count)
  17. {
  18. #ifdef WINDOWS
  19. m_semaphore = CreateSemaphore(NULL, count, 2147483647, NULL);
  20. if (m_semaphore == NULL) {
  21. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CreateSemaphore");
  22. }
  23. #elif defined(OSX)
  24. m_task = mach_task_self();
  25. if (semaphore_create(m_task, &m_semaphore, SYNC_POLICY_FIFO, count)) {
  26. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semaphore_create");
  27. }
  28. #elif defined(FREEBSD)
  29. m_semaphore = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
  30. if (m_semaphore < 0) {
  31. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semget");
  32. }
  33. semun init;
  34. init.val = count;
  35. if (semctl(m_semaphore, 0, SETVAL, init) < 0) {
  36. semctl(m_semaphore, 0, IPC_RMID);
  37. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semctl");
  38. }
  39. #else
  40. if (sem_init(&m_semaphore, 0, count)) {
  41. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("sem_init");
  42. }
  43. #endif
  44. }
  45. Semaphore::~Semaphore()
  46. {
  47. #ifdef WINDOWS
  48. MORDOR_NOTHROW_VERIFY(CloseHandle(m_semaphore));
  49. #elif defined(OSX)
  50. MORDOR_NOTHROW_VERIFY(!semaphore_destroy(m_task, m_semaphore));
  51. #elif defined(FREEBSD)
  52. MORDOR_NOTHROW_VERIFY(semctl(m_semaphore, 0, IPC_RMID) >= 0);
  53. #else
  54. MORDOR_NOTHROW_VERIFY(!sem_destroy(&m_semaphore));
  55. #endif
  56. }
  57. void
  58. Semaphore::wait()
  59. {
  60. #ifdef WINDOWS
  61. DWORD dwRet = WaitForSingleObject(m_semaphore, INFINITE);
  62. if (dwRet != WAIT_OBJECT_0) {
  63. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("WaitForSingleObject");
  64. }
  65. #elif defined(OSX)
  66. kern_return_t rc;
  67. do {
  68. rc = semaphore_wait(m_semaphore);
  69. } while (rc == KERN_ABORTED);
  70. if (rc != KERN_SUCCESS) {
  71. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semaphore_wait");
  72. }
  73. #elif defined(FREEBSD)
  74. sembuf op;
  75. op.sem_num = 0;
  76. op.sem_op = -1;
  77. op.sem_flg = 0;
  78. while (true) {
  79. if (!semop(m_semaphore, &op, 1))
  80. return;
  81. if (errno != EINTR) {
  82. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semop");
  83. }
  84. }
  85. #else
  86. while (true) {
  87. if (!sem_wait(&m_semaphore))
  88. return;
  89. if (errno != EINTR) {
  90. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("sem_wait");
  91. }
  92. }
  93. #endif
  94. }
  95. void
  96. Semaphore::notify()
  97. {
  98. #ifdef WINDOWS
  99. if (!ReleaseSemaphore(m_semaphore, 1, NULL)) {
  100. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("ReleaseSemaphore");
  101. }
  102. #elif defined(OSX)
  103. semaphore_signal(m_semaphore);
  104. #elif defined(FREEBSD)
  105. sembuf op;
  106. op.sem_num = 0;
  107. op.sem_op = 1;
  108. op.sem_flg = 0;
  109. if (semop(m_semaphore, &op, 1)) {
  110. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("semop");
  111. }
  112. #else
  113. if (sem_post(&m_semaphore)) {
  114. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("sem_post");
  115. }
  116. #endif
  117. }
  118. }