Jack2 1.9.6
|
00001 /* 00002 Copyright (C) 2004-2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as published by 00006 the Free Software Foundation; either version 2.1 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00018 */ 00019 00020 #include "JackPosixSemaphore.h" 00021 #include "JackTools.h" 00022 #include "JackConstants.h" 00023 #include "JackError.h" 00024 #include <fcntl.h> 00025 #include <stdio.h> 00026 #include <sys/time.h> 00027 00028 namespace Jack 00029 { 00030 00031 void JackPosixSemaphore::BuildName(const char* client_name, const char* server_name, char* res) 00032 { 00033 char ext_client_name[JACK_CLIENT_NAME_SIZE + 1]; 00034 JackTools::RewriteName(client_name, ext_client_name); 00035 sprintf(res, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); 00036 } 00037 00038 bool JackPosixSemaphore::Signal() 00039 { 00040 int res; 00041 00042 if (!fSemaphore) { 00043 jack_error("JackPosixSemaphore::Signal name = %s already desallocated!!", fName); 00044 return false; 00045 } 00046 00047 if (fFlush) 00048 return true; 00049 00050 if ((res = sem_post(fSemaphore)) != 0) { 00051 jack_error("JackPosixSemaphore::Signal name = %s err = %s", fName, strerror(errno)); 00052 } 00053 return (res == 0); 00054 } 00055 00056 bool JackPosixSemaphore::SignalAll() 00057 { 00058 int res; 00059 00060 if (!fSemaphore) { 00061 jack_error("JackPosixSemaphore::SignalAll name = %s already desallocated!!", fName); 00062 return false; 00063 } 00064 00065 if (fFlush) 00066 return true; 00067 00068 if ((res = sem_post(fSemaphore)) != 0) { 00069 jack_error("JackPosixSemaphore::SignalAll name = %s err = %s", fName, strerror(errno)); 00070 } 00071 return (res == 0); 00072 } 00073 00074 /* 00075 bool JackPosixSemaphore::Wait() 00076 { 00077 int res; 00078 00079 if (!fSemaphore) { 00080 jack_error("JackPosixSemaphore::Wait name = %s already desallocated!!", fName); 00081 return false; 00082 } 00083 00084 if ((res = sem_wait(fSemaphore)) != 0) { 00085 jack_error("JackPosixSemaphore::Wait name = %s err = %s", fName, strerror(errno)); 00086 } 00087 return (res == 0); 00088 } 00089 */ 00090 00091 bool JackPosixSemaphore::Wait() 00092 { 00093 int res; 00094 00095 while ((res = sem_wait(fSemaphore) < 0)) { 00096 jack_error("JackPosixSemaphore::Wait name = %s err = %s", fName, strerror(errno)); 00097 if (errno != EINTR) 00098 break; 00099 } 00100 return (res == 0); 00101 } 00102 00103 #if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) // glibc feature test 00104 00105 bool JackPosixSemaphore::TimedWait(long usec) 00106 { 00107 int res; 00108 struct timeval now; 00109 timespec time; 00110 00111 if (!fSemaphore) { 00112 jack_error("JackPosixSemaphore::TimedWait name = %s already desallocated!!", fName); 00113 return false; 00114 } 00115 gettimeofday(&now, 0); 00116 time.tv_sec = now.tv_sec + usec / 1000000; 00117 long tv_usec = (now.tv_usec + (usec % 1000000)); 00118 time.tv_sec += tv_usec / 1000000; 00119 time.tv_nsec = (tv_usec % 1000000) * 1000; 00120 00121 while ((res = sem_timedwait(fSemaphore, &time)) < 0) { 00122 jack_error("JackPosixSemaphore::TimedWait err = %s", strerror(errno)); 00123 jack_log("now %ld %ld ", now.tv_sec, now.tv_usec); 00124 jack_log("next %ld %ld ", time.tv_sec, time.tv_nsec/1000); 00125 if (errno != EINTR) 00126 break; 00127 } 00128 return (res == 0); 00129 } 00130 00131 #else 00132 #warning "JackPosixSemaphore::TimedWait is not supported: Jack in SYNC mode with JackPosixSemaphore will not run properly !!" 00133 00134 bool JackPosixSemaphore::TimedWait(long usec) 00135 { 00136 return Wait(); 00137 } 00138 #endif 00139 00140 // Server side : publish the semaphore in the global namespace 00141 bool JackPosixSemaphore::Allocate(const char* name, const char* server_name, int value) 00142 { 00143 BuildName(name, server_name, fName); 00144 jack_log("JackPosixSemaphore::Allocate name = %s val = %ld", fName, value); 00145 00146 if ((fSemaphore = sem_open(fName, O_CREAT, 0777, value)) == (sem_t*)SEM_FAILED) { 00147 jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno)); 00148 return false; 00149 } else { 00150 return true; 00151 } 00152 } 00153 00154 // Client side : get the published semaphore from server 00155 bool JackPosixSemaphore::ConnectInput(const char* name, const char* server_name) 00156 { 00157 BuildName(name, server_name, fName); 00158 jack_log("JackPosixSemaphore::Connect %s", fName); 00159 00160 // Temporary... 00161 if (fSemaphore) { 00162 jack_log("Already connected name = %s", name); 00163 return true; 00164 } 00165 00166 if ((fSemaphore = sem_open(fName, O_CREAT)) == (sem_t*)SEM_FAILED) { 00167 jack_error("Connect: can't connect named semaphore name = %s err = %s", fName, strerror(errno)); 00168 return false; 00169 } else { 00170 int val = 0; 00171 sem_getvalue(fSemaphore, &val); 00172 jack_log("JackPosixSemaphore::Connect sem_getvalue %ld", val); 00173 return true; 00174 } 00175 } 00176 00177 bool JackPosixSemaphore::Connect(const char* name, const char* server_name) 00178 { 00179 return ConnectInput(name, server_name); 00180 } 00181 00182 bool JackPosixSemaphore::ConnectOutput(const char* name, const char* server_name) 00183 { 00184 return ConnectInput(name, server_name); 00185 } 00186 00187 bool JackPosixSemaphore::Disconnect() 00188 { 00189 if (fSemaphore) { 00190 jack_log("JackPosixSemaphore::Disconnect %s", fName); 00191 if (sem_close(fSemaphore) != 0) { 00192 jack_error("Disconnect: can't disconnect named semaphore name = %s err = %s", fName, strerror(errno)); 00193 return false; 00194 } else { 00195 fSemaphore = NULL; 00196 return true; 00197 } 00198 } else { 00199 return true; 00200 } 00201 } 00202 00203 // Server side : destroy the semaphore 00204 void JackPosixSemaphore::Destroy() 00205 { 00206 if (fSemaphore != NULL) { 00207 jack_log("JackPosixSemaphore::Destroy"); 00208 sem_unlink(fName); 00209 if (sem_close(fSemaphore) != 0) { 00210 jack_error("Destroy: can't destroy semaphore name = %s err = %s", fName, strerror(errno)); 00211 } 00212 fSemaphore = NULL; 00213 } else { 00214 jack_error("JackPosixSemaphore::Destroy semaphore == NULL"); 00215 } 00216 } 00217 00218 } // end of namespace 00219