jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
5.8KB

  1. /*
  2. Copyright (C) 2004-2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 2.1 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #include "JackPosixSemaphore.h"
  16. #include "JackConstants.h"
  17. #include "JackError.h"
  18. #include <fcntl.h>
  19. #include <stdio.h>
  20. #include <sys/time.h>
  21. namespace Jack
  22. {
  23. void JackPosixSemaphore::BuildName(const char* name, const char* server_name, char* res)
  24. {
  25. sprintf(res, "jack_sem.%s_%s", server_name, name);
  26. }
  27. bool JackPosixSemaphore::Signal()
  28. {
  29. int res;
  30. if (!fSemaphore) {
  31. jack_error("JackPosixSemaphore::Signal name = %s already desallocated!!", fName);
  32. return false;
  33. }
  34. if (fFlush)
  35. return true;
  36. if ((res = sem_post(fSemaphore)) != 0) {
  37. jack_error("JackPosixSemaphore::Signal name = %s err = %s", fName, strerror(errno));
  38. }
  39. return (res == 0);
  40. }
  41. bool JackPosixSemaphore::SignalAll()
  42. {
  43. int res;
  44. if (!fSemaphore) {
  45. jack_error("JackPosixSemaphore::SignalAll name = %s already desallocated!!", fName);
  46. return false;
  47. }
  48. if (fFlush)
  49. return true;
  50. if ((res = sem_post(fSemaphore)) != 0) {
  51. jack_error("JackPosixSemaphore::SignalAll name = %s err = %s", fName, strerror(errno));
  52. }
  53. return (res == 0);
  54. }
  55. /*
  56. bool JackPosixSemaphore::Wait()
  57. {
  58. int res;
  59. if (!fSemaphore) {
  60. jack_error("JackPosixSemaphore::Wait name = %s already desallocated!!", fName);
  61. return false;
  62. }
  63. if ((res = sem_wait(fSemaphore)) != 0) {
  64. jack_error("JackPosixSemaphore::Wait name = %s err = %s", fName, strerror(errno));
  65. }
  66. return (res == 0);
  67. }
  68. */
  69. bool JackPosixSemaphore::Wait()
  70. {
  71. int res;
  72. while ((res = sem_wait(fSemaphore) < 0)) {
  73. jack_error("JackPosixSemaphore::Wait name = %s err = %s", fName, strerror(errno));
  74. if (errno != EINTR)
  75. break;
  76. }
  77. return (res == 0);
  78. }
  79. #if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) // glibc feature test
  80. bool JackPosixSemaphore::TimedWait(long usec)
  81. {
  82. int res;
  83. struct timeval now;
  84. timespec time;
  85. if (!fSemaphore) {
  86. jack_error("JackPosixSemaphore::TimedWait name = %s already desallocated!!", fName);
  87. return false;
  88. }
  89. gettimeofday(&now, 0);
  90. time.tv_sec = now.tv_sec + usec / 1000000;
  91. long tv_usec = (now.tv_usec + (usec % 1000000));
  92. time.tv_sec += tv_usec / 1000000;
  93. time.tv_nsec = (tv_usec % 1000000) * 1000;
  94. if ((res = sem_timedwait(fSemaphore, &time)) != 0) {
  95. jack_error("JackPosixSemaphore::TimedWait err = %s", strerror(errno));
  96. jack_log("now %ld %ld ", now.tv_sec, now.tv_usec);
  97. jack_log("next %ld %ld ", time.tv_sec, time.tv_nsec/1000);
  98. }
  99. return (res == 0);
  100. }
  101. #else
  102. #warning "JackPosixSemaphore::TimedWait is not supported: Jack in SYNC mode with JackPosixSemaphore will not run properly !!"
  103. bool JackPosixSemaphore::TimedWait(long usec)
  104. {
  105. return Wait();
  106. }
  107. #endif
  108. // Server side : publish the semaphore in the global namespace
  109. bool JackPosixSemaphore::Allocate(const char* name, const char* server_name, int value)
  110. {
  111. BuildName(name, server_name, fName);
  112. jack_log("JackPosixSemaphore::Allocate name = %s val = %ld", fName, value);
  113. if ((fSemaphore = sem_open(fName, O_CREAT, 0777, value)) == (sem_t*)SEM_FAILED) {
  114. jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno));
  115. return false;
  116. } else {
  117. return true;
  118. }
  119. }
  120. // Client side : get the published semaphore from server
  121. bool JackPosixSemaphore::ConnectInput(const char* name, const char* server_name)
  122. {
  123. BuildName(name, server_name, fName);
  124. jack_log("JackPosixSemaphore::Connect %s", fName);
  125. // Temporary...
  126. if (fSemaphore) {
  127. jack_log("Already connected name = %s", name);
  128. return true;
  129. }
  130. if ((fSemaphore = sem_open(fName, O_CREAT)) == (sem_t*)SEM_FAILED) {
  131. jack_error("Connect: can't connect named semaphore name = %s err = %s", fName, strerror(errno));
  132. return false;
  133. } else {
  134. int val = 0;
  135. sem_getvalue(fSemaphore, &val);
  136. jack_log("JackPosixSemaphore::Connect sem_getvalue %ld", val);
  137. return true;
  138. }
  139. }
  140. bool JackPosixSemaphore::Connect(const char* name, const char* server_name)
  141. {
  142. return ConnectInput(name, server_name);
  143. }
  144. bool JackPosixSemaphore::ConnectOutput(const char* name, const char* server_name)
  145. {
  146. return ConnectInput(name, server_name);
  147. }
  148. bool JackPosixSemaphore::Disconnect()
  149. {
  150. jack_log("JackPosixSemaphore::Disconnect %s", fName);
  151. if (fSemaphore) {
  152. if (sem_close(fSemaphore) != 0) {
  153. jack_error("Disconnect: can't disconnect named semaphore name = %s err = %s", fName, strerror(errno));
  154. return false;
  155. } else {
  156. fSemaphore = NULL;
  157. return true;
  158. }
  159. } else {
  160. return true;
  161. }
  162. }
  163. // Server side : destroy the semaphore
  164. void JackPosixSemaphore::Destroy()
  165. {
  166. if (fSemaphore != NULL) {
  167. jack_log("JackPosixSemaphore::Destroy");
  168. sem_unlink(fName);
  169. if (sem_close(fSemaphore) != 0) {
  170. jack_error("Destroy: can't destroy semaphore name = %s err = %s", fName, strerror(errno));
  171. }
  172. fSemaphore = NULL;
  173. } else {
  174. jack_error("JackPosixSemaphore::Destroy semaphore == NULL");
  175. }
  176. }
  177. } // end of namespace