Mutex_POSIX.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. //
  2. // Mutex_POSIX.cpp
  3. //
  4. // $Id: //poco/1.4/Foundation/src/Mutex_POSIX.cpp#4 $
  5. //
  6. // Library: Foundation
  7. // Package: Threading
  8. // Module: Mutex
  9. //
  10. // Copyright (c) 2004-2008, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #include "Poco/Mutex_POSIX.h"
  16. #include "Poco/Timestamp.h"
  17. #if !defined(POCO_NO_SYS_SELECT_H)
  18. #include <sys/select.h>
  19. #endif
  20. #include <unistd.h>
  21. #if defined(POCO_VXWORKS)
  22. #include <timers.h>
  23. #include <cstring>
  24. #else
  25. #include <sys/time.h>
  26. #endif
  27. #if defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS - 200112L) >= 0L
  28. #if defined(_POSIX_THREADS) && (_POSIX_THREADS - 200112L) >= 0L
  29. #define POCO_HAVE_MUTEX_TIMEOUT
  30. #endif
  31. #endif
  32. namespace Poco {
  33. MutexImpl::MutexImpl()
  34. {
  35. #if defined(POCO_VXWORKS)
  36. // This workaround is for VxWorks 5.x where
  37. // pthread_mutex_init() won't properly initialize the mutex
  38. // resulting in a subsequent freeze in pthread_mutex_destroy()
  39. // if the mutex has never been used.
  40. std::memset(&_mutex, 0, sizeof(_mutex));
  41. #endif
  42. pthread_mutexattr_t attr;
  43. pthread_mutexattr_init(&attr);
  44. #if defined(PTHREAD_MUTEX_RECURSIVE_NP)
  45. pthread_mutexattr_settype_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
  46. #elif !defined(POCO_VXWORKS)
  47. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  48. #endif
  49. if (pthread_mutex_init(&_mutex, &attr))
  50. {
  51. pthread_mutexattr_destroy(&attr);
  52. throw SystemException("cannot create mutex");
  53. }
  54. pthread_mutexattr_destroy(&attr);
  55. }
  56. MutexImpl::MutexImpl(bool fast)
  57. {
  58. #if defined(POCO_VXWORKS)
  59. // This workaround is for VxWorks 5.x where
  60. // pthread_mutex_init() won't properly initialize the mutex
  61. // resulting in a subsequent freeze in pthread_mutex_destroy()
  62. // if the mutex has never been used.
  63. std::memset(&_mutex, 0, sizeof(_mutex));
  64. #endif
  65. pthread_mutexattr_t attr;
  66. pthread_mutexattr_init(&attr);
  67. #if defined(PTHREAD_MUTEX_RECURSIVE_NP)
  68. pthread_mutexattr_settype_np(&attr, fast ? PTHREAD_MUTEX_NORMAL_NP : PTHREAD_MUTEX_RECURSIVE_NP);
  69. #elif !defined(POCO_VXWORKS)
  70. pthread_mutexattr_settype(&attr, fast ? PTHREAD_MUTEX_NORMAL : PTHREAD_MUTEX_RECURSIVE);
  71. #endif
  72. if (pthread_mutex_init(&_mutex, &attr))
  73. {
  74. pthread_mutexattr_destroy(&attr);
  75. throw SystemException("cannot create mutex");
  76. }
  77. pthread_mutexattr_destroy(&attr);
  78. }
  79. MutexImpl::~MutexImpl()
  80. {
  81. pthread_mutex_destroy(&_mutex);
  82. }
  83. bool MutexImpl::tryLockImpl(long milliseconds)
  84. {
  85. #if defined(POCO_HAVE_MUTEX_TIMEOUT)
  86. struct timespec abstime;
  87. struct timeval tv;
  88. gettimeofday(&tv, NULL);
  89. abstime.tv_sec = tv.tv_sec + milliseconds / 1000;
  90. abstime.tv_nsec = tv.tv_usec*1000 + (milliseconds % 1000)*1000000;
  91. if (abstime.tv_nsec >= 1000000000)
  92. {
  93. abstime.tv_nsec -= 1000000000;
  94. abstime.tv_sec++;
  95. }
  96. int rc = pthread_mutex_timedlock(&_mutex, &abstime);
  97. if (rc == 0)
  98. return true;
  99. else if (rc == ETIMEDOUT)
  100. return false;
  101. else
  102. throw SystemException("cannot lock mutex");
  103. #else
  104. const int sleepMillis = 5;
  105. Timestamp now;
  106. Timestamp::TimeDiff diff(Timestamp::TimeDiff(milliseconds)*1000);
  107. do
  108. {
  109. int rc = pthread_mutex_trylock(&_mutex);
  110. if (rc == 0)
  111. return true;
  112. else if (rc != EBUSY)
  113. throw SystemException("cannot lock mutex");
  114. #if defined(POCO_VXWORKS)
  115. struct timespec ts;
  116. ts.tv_sec = 0;
  117. ts.tv_nsec = sleepMillis*1000000;
  118. nanosleep(&ts, NULL);
  119. #else
  120. struct timeval tv;
  121. tv.tv_sec = 0;
  122. tv.tv_usec = sleepMillis * 1000;
  123. select(0, NULL, NULL, NULL, &tv);
  124. #endif
  125. }
  126. while (!now.isElapsed(diff));
  127. return false;
  128. #endif
  129. }
  130. FastMutexImpl::FastMutexImpl(): MutexImpl(true)
  131. {
  132. }
  133. FastMutexImpl::~FastMutexImpl()
  134. {
  135. }
  136. } // namespace Poco