Jack2  1.9.10
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, 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