JackMachSemaphore.cpp

00001 /*
00002 Copyright (C) 2004-2006 Grame  
00003 
00004 This program is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 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 General Public License for more details.
00013 
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 
00018 */
00019 
00020 #include "JackMachSemaphore.h"
00021 #include "JackError.h"
00022 #include <stdio.h>
00023 #include <assert.h>
00024 
00025 namespace Jack
00026 {
00027 
00028 mach_port_t JackMachSemaphore::fBootPort = 0;
00029 
00030 void JackMachSemaphore::BuildName(const char* name, char* res)
00031 {
00032     sprintf(res, "jack_mach_sem.%s", name);
00033 }
00034 
00035 bool JackMachSemaphore::Signal()
00036 {
00037     kern_return_t res;
00038     assert(fSemaphore > 0);
00039 
00040     if (fFlush)
00041         return true;
00042 
00043     if ((res = semaphore_signal(fSemaphore)) != KERN_SUCCESS) {
00044         jack_error("JackMachSemaphore::Signal name = %s err = %s", fName, mach_error_string(res));
00045     }
00046     return (res == KERN_SUCCESS);
00047 }
00048 
00049 bool JackMachSemaphore::SignalAll()
00050 {
00051     kern_return_t res;
00052     assert(fSemaphore > 0);
00053 
00054     if (fFlush)
00055         return true;
00056     // When signaled several times, do not accumulate signals...
00057     if ((res = semaphore_signal_all(fSemaphore)) != KERN_SUCCESS) {
00058         jack_error("JackMachSemaphore::SignalAll name = %s err = %s", fName, mach_error_string(res));
00059     }
00060     return (res == KERN_SUCCESS);
00061 }
00062 
00063 bool JackMachSemaphore::Wait()
00064 {
00065     kern_return_t res;
00066     assert(fSemaphore > 0);
00067     if ((res = semaphore_wait(fSemaphore)) != KERN_SUCCESS) {
00068         jack_error("JackMachSemaphore::Wait name = %s err = %s", fName, mach_error_string(res));
00069     }
00070     return (res == KERN_SUCCESS);
00071 }
00072 
00073 bool JackMachSemaphore::TimedWait(long usec)
00074 {
00075     kern_return_t res;
00076     mach_timespec time;
00077     time.tv_sec = usec / 1000000;
00078     time.tv_nsec = (usec % 1000000) * 1000;
00079     assert(fSemaphore > 0);
00080     if ((res = semaphore_timedwait(fSemaphore, time)) != KERN_SUCCESS) {
00081         jack_error("JackMachSemaphore::TimedWait name = %s err = %s", fName, mach_error_string(res));
00082     }
00083     return (res == KERN_SUCCESS);
00084 }
00085 
00086 // Server side : publish the semaphore in the global namespace
00087 bool JackMachSemaphore::Allocate(const char* name, int value)
00088 {
00089     BuildName(name, fName);
00090     mach_port_t task = mach_task_self();
00091     kern_return_t res;
00092 
00093     if (fBootPort == 0) {
00094         if ((res = task_get_bootstrap_port(task, &fBootPort)) != KERN_SUCCESS) {
00095             jack_error("Allocate: Can't find bootstrap mach port err = %s", mach_error_string(res));
00096             return false;
00097         }
00098     }
00099 
00100     if ((res = semaphore_create(task, &fSemaphore, SYNC_POLICY_FIFO, value)) != KERN_SUCCESS) {
00101         jack_error("Allocate: can create semaphore err = %s", mach_error_string(res));
00102         return false;
00103     }
00104 
00105     if ((res = bootstrap_register(fBootPort, fName, fSemaphore)) != KERN_SUCCESS) {
00106         jack_error("Allocate: can't check in mach semaphore name = %s err = %s", fName, mach_error_string(res));
00107 
00108         switch (res) {
00109             case BOOTSTRAP_SUCCESS :
00110                 /* service not currently registered, "a good thing" (tm) */
00111                 break;
00112             case BOOTSTRAP_NOT_PRIVILEGED :
00113                 JackLog("bootstrap_register(): bootstrap not privileged\n");
00114                 break;
00115             case BOOTSTRAP_SERVICE_ACTIVE :
00116                 JackLog("bootstrap_register(): bootstrap service active\n");
00117                 break;
00118             default :
00119                 JackLog("bootstrap_register() err = %s\n", mach_error_string(res));
00120                 break;
00121         }
00122 
00123         return false;
00124     }
00125 
00126     JackLog("JackMachSemaphore::Allocate name = %s\n", fName);
00127     return true;
00128 }
00129 
00130 // Client side : get the published semaphore from server
00131 bool JackMachSemaphore::ConnectInput(const char* name)
00132 {
00133     BuildName(name, fName);
00134     kern_return_t res;
00135 
00136     // Temporary...  A REVOIR
00137     /*
00138     if (fSemaphore > 0) {
00139         JackLog("Already connected name = %s\n", name);
00140         return true;
00141     }
00142     */
00143 
00144     if (fBootPort == 0) {
00145         if ((res = task_get_bootstrap_port(mach_task_self(), &fBootPort)) != KERN_SUCCESS) {
00146             jack_error("Connect: can't find bootstrap port err = %s", mach_error_string(res));
00147             return false;
00148         }
00149     }
00150 
00151     if ((res = bootstrap_look_up(fBootPort, fName, &fSemaphore)) != KERN_SUCCESS) {
00152         jack_error("Connect: can't find mach semaphore name = %s err = %s", fName, mach_error_string(res));
00153         return false;
00154     }
00155 
00156     JackLog("JackMachSemaphore::Connect name = %s \n", fName);
00157     return true;
00158 }
00159 
00160 bool JackMachSemaphore::Connect(const char* name)
00161 {
00162     return ConnectInput(name);
00163 }
00164 
00165 bool JackMachSemaphore::ConnectOutput(const char* name)
00166 {
00167     return ConnectInput(name);
00168 }
00169 
00170 bool JackMachSemaphore::Disconnect()
00171 {
00172         if (fSemaphore > 0) {
00173                 JackLog("JackMachSemaphore::Disconnect name = %s\n", fName);
00174         }
00175     // Nothing to do
00176     return true;
00177 }
00178 
00179 // Server side : destroy the JackGlobals
00180 void JackMachSemaphore::Destroy()
00181 {
00182     kern_return_t res;
00183 
00184     if (fSemaphore > 0) {
00185         JackLog("JackMachSemaphore::Destroy\n");
00186         if ((res = semaphore_destroy(mach_task_self(), fSemaphore)) != KERN_SUCCESS) {
00187             jack_error("JackMachSemaphore::Destroy can't destroy semaphore err = %s", mach_error_string(res));
00188         }
00189         fSemaphore = 0;
00190     } else {
00191         jack_error("JackMachSemaphore::Destroy semaphore < 0");
00192     }
00193 }
00194 
00195 } // end of namespace
00196 

Generated on Wed Jan 10 11:42:45 2007 for Jackdmp by  doxygen 1.4.5