Semaphore_POSIX.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. //
  2. // Semaphore_POSIX.cpp
  3. //
  4. // $Id: //poco/1.4/Foundation/src/Semaphore_POSIX.cpp#3 $
  5. //
  6. // Library: Foundation
  7. // Package: Threading
  8. // Module: Semaphore
  9. //
  10. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #include "Poco/Semaphore_POSIX.h"
  16. #if defined(POCO_VXWORKS)
  17. #include <timers.h>
  18. #include <cstring>
  19. #else
  20. #include <sys/time.h>
  21. #endif
  22. namespace Poco {
  23. SemaphoreImpl::SemaphoreImpl(int n, int max): _n(n), _max(max)
  24. {
  25. poco_assert (n >= 0 && max > 0 && n <= max);
  26. #if defined(POCO_VXWORKS)
  27. // This workaround is for VxWorks 5.x where
  28. // pthread_mutex_init() won't properly initialize the mutex
  29. // resulting in a subsequent freeze in pthread_mutex_destroy()
  30. // if the mutex has never been used.
  31. std::memset(&_mutex, 0, sizeof(_mutex));
  32. #endif
  33. if (pthread_mutex_init(&_mutex, NULL))
  34. throw SystemException("cannot create semaphore (mutex)");
  35. if (pthread_cond_init(&_cond, NULL))
  36. throw SystemException("cannot create semaphore (condition)");
  37. }
  38. SemaphoreImpl::~SemaphoreImpl()
  39. {
  40. pthread_cond_destroy(&_cond);
  41. pthread_mutex_destroy(&_mutex);
  42. }
  43. void SemaphoreImpl::waitImpl()
  44. {
  45. if (pthread_mutex_lock(&_mutex))
  46. throw SystemException("wait for semaphore failed (lock)");
  47. while (_n < 1)
  48. {
  49. if (pthread_cond_wait(&_cond, &_mutex))
  50. {
  51. pthread_mutex_unlock(&_mutex);
  52. throw SystemException("wait for semaphore failed");
  53. }
  54. }
  55. --_n;
  56. pthread_mutex_unlock(&_mutex);
  57. }
  58. bool SemaphoreImpl::waitImpl(long milliseconds)
  59. {
  60. int rc = 0;
  61. struct timespec abstime;
  62. #if defined(__VMS)
  63. struct timespec delta;
  64. delta.tv_sec = milliseconds / 1000;
  65. delta.tv_nsec = (milliseconds % 1000)*1000000;
  66. pthread_get_expiration_np(&delta, &abstime);
  67. #elif defined(POCO_VXWORKS)
  68. clock_gettime(CLOCK_REALTIME, &abstime);
  69. abstime.tv_sec += milliseconds / 1000;
  70. abstime.tv_nsec += (milliseconds % 1000)*1000000;
  71. if (abstime.tv_nsec >= 1000000000)
  72. {
  73. abstime.tv_nsec -= 1000000000;
  74. abstime.tv_sec++;
  75. }
  76. #else
  77. struct timeval tv;
  78. gettimeofday(&tv, NULL);
  79. abstime.tv_sec = tv.tv_sec + milliseconds / 1000;
  80. abstime.tv_nsec = tv.tv_usec*1000 + (milliseconds % 1000)*1000000;
  81. if (abstime.tv_nsec >= 1000000000)
  82. {
  83. abstime.tv_nsec -= 1000000000;
  84. abstime.tv_sec++;
  85. }
  86. #endif
  87. if (pthread_mutex_lock(&_mutex) != 0)
  88. throw SystemException("wait for semaphore failed (lock)");
  89. while (_n < 1)
  90. {
  91. if ((rc = pthread_cond_timedwait(&_cond, &_mutex, &abstime)))
  92. {
  93. if (rc == ETIMEDOUT) break;
  94. pthread_mutex_unlock(&_mutex);
  95. throw SystemException("cannot wait for semaphore");
  96. }
  97. }
  98. if (rc == 0) --_n;
  99. pthread_mutex_unlock(&_mutex);
  100. return rc == 0;
  101. }
  102. } // namespace Poco