Jack2 1.9.6

JackPosixSemaphore.cpp

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