Jack2 1.9.10
|
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, int size) 00032 { 00033 char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; 00034 JackTools::RewriteName(client_name, ext_client_name); 00035 if (getenv("JACK_PROMISCUOUS_SERVER")) { 00036 snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); 00037 } else { 00038 snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); 00039 } 00040 } 00041 00042 bool JackPosixSemaphore::Signal() 00043 { 00044 int res; 00045 00046 if (!fSemaphore) { 00047 jack_error("JackPosixSemaphore::Signal name = %s already deallocated!!", fName); 00048 return false; 00049 } 00050 00051 if (fFlush) 00052 return true; 00053 00054 if ((res = sem_post(fSemaphore)) != 0) { 00055 jack_error("JackPosixSemaphore::Signal name = %s err = %s", fName, strerror(errno)); 00056 } 00057 return (res == 0); 00058 } 00059 00060 bool JackPosixSemaphore::SignalAll() 00061 { 00062 int res; 00063 00064 if (!fSemaphore) { 00065 jack_error("JackPosixSemaphore::SignalAll name = %s already deallocated!!", fName); 00066 return false; 00067 } 00068 00069 if (fFlush) 00070 return true; 00071 00072 if ((res = sem_post(fSemaphore)) != 0) { 00073 jack_error("JackPosixSemaphore::SignalAll name = %s err = %s", fName, strerror(errno)); 00074 } 00075 return (res == 0); 00076 } 00077 00078 /* 00079 bool JackPosixSemaphore::Wait() 00080 { 00081 int res; 00082 00083 if (!fSemaphore) { 00084 jack_error("JackPosixSemaphore::Wait name = %s already deallocated!!", fName); 00085 return false; 00086 } 00087 00088 if ((res = sem_wait(fSemaphore)) != 0) { 00089 jack_error("JackPosixSemaphore::Wait name = %s err = %s", fName, strerror(errno)); 00090 } 00091 return (res == 0); 00092 } 00093 */ 00094 00095 bool JackPosixSemaphore::Wait() 00096 { 00097 int res; 00098 00099 while ((res = sem_wait(fSemaphore) < 0)) { 00100 jack_error("JackPosixSemaphore::Wait name = %s err = %s", fName, strerror(errno)); 00101 if (errno != EINTR) { 00102 break; 00103 } 00104 } 00105 return (res == 0); 00106 } 00107 00108 #if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) // glibc feature test 00109 00110 bool JackPosixSemaphore::TimedWait(long usec) 00111 { 00112 int res; 00113 struct timeval now; 00114 timespec time; 00115 00116 if (!fSemaphore) { 00117 jack_error("JackPosixSemaphore::TimedWait name = %s already deallocated!!", fName); 00118 return false; 00119 } 00120 gettimeofday(&now, 0); 00121 time.tv_sec = now.tv_sec + usec / 1000000; 00122 long tv_usec = (now.tv_usec + (usec % 1000000)); 00123 time.tv_sec += tv_usec / 1000000; 00124 time.tv_nsec = (tv_usec % 1000000) * 1000; 00125 00126 while ((res = sem_timedwait(fSemaphore, &time)) < 0) { 00127 jack_error("JackPosixSemaphore::TimedWait err = %s", strerror(errno)); 00128 jack_log("JackPosixSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec); 00129 jack_log("JackPosixSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000); 00130 if (errno != EINTR) { 00131 break; 00132 } 00133 } 00134 return (res == 0); 00135 } 00136 00137 #else 00138 #warning "JackPosixSemaphore::TimedWait is not supported: Jack in SYNC mode with JackPosixSemaphore will not run properly !!" 00139 00140 bool JackPosixSemaphore::TimedWait(long usec) 00141 { 00142 return Wait(); 00143 } 00144 #endif 00145 00146 // Server side : publish the semaphore in the global namespace 00147 bool JackPosixSemaphore::Allocate(const char* name, const char* server_name, int value) 00148 { 00149 BuildName(name, server_name, fName, sizeof(fName)); 00150 jack_log("JackPosixSemaphore::Allocate name = %s val = %ld", fName, value); 00151 00152 if ((fSemaphore = sem_open(fName, O_CREAT | O_RDWR, 0777, value)) == (sem_t*)SEM_FAILED) { 00153 jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno)); 00154 return false; 00155 } else { 00156 return true; 00157 } 00158 } 00159 00160 // Client side : get the published semaphore from server 00161 bool JackPosixSemaphore::ConnectInput(const char* name, const char* server_name) 00162 { 00163 BuildName(name, server_name, fName, sizeof(fName)); 00164 jack_log("JackPosixSemaphore::Connect name = %s", fName); 00165 00166 // Temporary... 00167 if (fSemaphore) { 00168 jack_log("Already connected name = %s", name); 00169 return true; 00170 } 00171 00172 if ((fSemaphore = sem_open(fName, O_RDWR)) == (sem_t*)SEM_FAILED) { 00173 jack_error("Connect: can't connect named semaphore name = %s err = %s", fName, strerror(errno)); 00174 return false; 00175 } else { 00176 int val = 0; 00177 sem_getvalue(fSemaphore, &val); 00178 jack_log("JackPosixSemaphore::Connect sem_getvalue %ld", val); 00179 return true; 00180 } 00181 } 00182 00183 bool JackPosixSemaphore::Connect(const char* name, const char* server_name) 00184 { 00185 return ConnectInput(name, server_name); 00186 } 00187 00188 bool JackPosixSemaphore::ConnectOutput(const char* name, const char* server_name) 00189 { 00190 return ConnectInput(name, server_name); 00191 } 00192 00193 bool JackPosixSemaphore::Disconnect() 00194 { 00195 if (fSemaphore) { 00196 jack_log("JackPosixSemaphore::Disconnect name = %s", fName); 00197 if (sem_close(fSemaphore) != 0) { 00198 jack_error("Disconnect: can't disconnect named semaphore name = %s err = %s", fName, strerror(errno)); 00199 return false; 00200 } else { 00201 fSemaphore = NULL; 00202 return true; 00203 } 00204 } else { 00205 return true; 00206 } 00207 } 00208 00209 // Server side : destroy the semaphore 00210 void JackPosixSemaphore::Destroy() 00211 { 00212 if (fSemaphore != NULL) { 00213 jack_log("JackPosixSemaphore::Destroy name = %s", fName); 00214 sem_unlink(fName); 00215 if (sem_close(fSemaphore) != 0) { 00216 jack_error("Destroy: can't destroy semaphore name = %s err = %s", fName, strerror(errno)); 00217 } 00218 fSemaphore = NULL; 00219 } else { 00220 jack_error("JackPosixSemaphore::Destroy semaphore == NULL"); 00221 } 00222 } 00223 00224 } // end of namespace 00225