JackMachSemaphore.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 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 
00024 namespace Jack
00025 {
00026 
00027 mach_port_t JackMachSemaphore::fBootPort = 0;
00028 
00029 void JackMachSemaphore::BuildName(const char* name, const char* server_name, char* res)
00030 {
00031     sprintf(res, "jack_mach_sem.%s_%s", server_name, name);
00032 }
00033 
00034 bool JackMachSemaphore::Signal()
00035 {
00036     kern_return_t res;
00037         
00038         if (!fSemaphore) {
00039                 jack_error("JackMachSemaphore::Signal name = %s already desallocated!!", fName);
00040                 return false;
00041         }
00042 
00043     if (fFlush)
00044         return true;
00045 
00046     if ((res = semaphore_signal(fSemaphore)) != KERN_SUCCESS) {
00047         jack_error("JackMachSemaphore::Signal name = %s err = %s", fName, mach_error_string(res));
00048     }
00049     return (res == KERN_SUCCESS);
00050 }
00051 
00052 bool JackMachSemaphore::SignalAll()
00053 {
00054     kern_return_t res;
00055         
00056     if (!fSemaphore) {
00057                 jack_error("JackMachSemaphore::SignalAll name = %s already desallocated!!", fName);
00058                 return false;
00059         }
00060 
00061     if (fFlush)
00062         return true;
00063     // When signaled several times, do not accumulate signals...
00064     if ((res = semaphore_signal_all(fSemaphore)) != KERN_SUCCESS) {
00065         jack_error("JackMachSemaphore::SignalAll name = %s err = %s", fName, mach_error_string(res));
00066     }
00067     return (res == KERN_SUCCESS);
00068 }
00069 
00070 bool JackMachSemaphore::Wait()
00071 {
00072     kern_return_t res;
00073         
00074     if (!fSemaphore) {
00075                 jack_error("JackMachSemaphore::Wait name = %s already desallocated!!", fName);
00076                 return false;
00077         }
00078         
00079     if ((res = semaphore_wait(fSemaphore)) != KERN_SUCCESS) {
00080         jack_error("JackMachSemaphore::Wait name = %s err = %s", fName, mach_error_string(res));
00081     }
00082     return (res == KERN_SUCCESS);
00083 }
00084 
00085 bool JackMachSemaphore::TimedWait(long usec)
00086 {
00087     kern_return_t res;
00088     mach_timespec time;
00089     time.tv_sec = usec / 1000000;
00090     time.tv_nsec = (usec % 1000000) * 1000;
00091         
00092         if (!fSemaphore) {
00093                 jack_error("JackMachSemaphore::TimedWait name = %s already desallocated!!", fName);
00094                 return false;
00095         }
00096 
00097     if ((res = semaphore_timedwait(fSemaphore, time)) != KERN_SUCCESS) {
00098         jack_error("JackMachSemaphore::TimedWait name = %s usec = %ld err = %s", fName, usec, mach_error_string(res));
00099     }
00100     return (res == KERN_SUCCESS);
00101 }
00102 
00103 // Server side : publish the semaphore in the global namespace
00104 bool JackMachSemaphore::Allocate(const char* name, const char* server_name, int value)
00105 {
00106     BuildName(name, server_name, fName);
00107     mach_port_t task = mach_task_self();
00108     kern_return_t res;
00109 
00110     if (fBootPort == 0) {
00111         if ((res = task_get_bootstrap_port(task, &fBootPort)) != KERN_SUCCESS) {
00112             jack_error("Allocate: Can't find bootstrap mach port err = %s", mach_error_string(res));
00113             return false;
00114         }
00115     }
00116 
00117     if ((res = semaphore_create(task, &fSemaphore, SYNC_POLICY_FIFO, value)) != KERN_SUCCESS) {
00118         jack_error("Allocate: can create semaphore err = %s", mach_error_string(res));
00119         return false;
00120     }
00121 
00122     if ((res = bootstrap_register(fBootPort, fName, fSemaphore)) != KERN_SUCCESS) {
00123         jack_error("Allocate: can't check in mach semaphore name = %s err = %s", fName, mach_error_string(res));
00124 
00125         switch (res) {
00126             case BOOTSTRAP_SUCCESS :
00127                 /* service not currently registered, "a good thing" (tm) */
00128                 break;
00129             case BOOTSTRAP_NOT_PRIVILEGED :
00130                 JackLog("bootstrap_register(): bootstrap not privileged\n");
00131                 break;
00132             case BOOTSTRAP_SERVICE_ACTIVE :
00133                 JackLog("bootstrap_register(): bootstrap service active\n");
00134                 break;
00135             default :
00136                 JackLog("bootstrap_register() err = %s\n", mach_error_string(res));
00137                 break;
00138         }
00139 
00140         return false;
00141     }
00142 
00143     JackLog("JackMachSemaphore::Allocate name = %s\n", fName);
00144     return true;
00145 }
00146 
00147 // Client side : get the published semaphore from server
00148 bool JackMachSemaphore::ConnectInput(const char* name, const char* server_name)
00149 {
00150     BuildName(name, server_name, fName);
00151     kern_return_t res;
00152 
00153     // Temporary...  A REVOIR
00154     /*
00155     if (fSemaphore > 0) {
00156         JackLog("Already connected name = %s\n", name);
00157         return true;
00158     }
00159     */
00160 
00161     if (fBootPort == 0) {
00162         if ((res = task_get_bootstrap_port(mach_task_self(), &fBootPort)) != KERN_SUCCESS) {
00163             jack_error("Connect: can't find bootstrap port err = %s", mach_error_string(res));
00164             return false;
00165         }
00166     }
00167 
00168     if ((res = bootstrap_look_up(fBootPort, fName, &fSemaphore)) != KERN_SUCCESS) {
00169         jack_error("Connect: can't find mach semaphore name = %s err = %s", fName, mach_error_string(res));
00170         return false;
00171     }
00172 
00173     JackLog("JackMachSemaphore::Connect name = %s \n", fName);
00174     return true;
00175 }
00176 
00177 bool JackMachSemaphore::Connect(const char* name, const char* server_name)
00178 {
00179     return ConnectInput(name, server_name);
00180 }
00181 
00182 bool JackMachSemaphore::ConnectOutput(const char* name, const char* server_name)
00183 {
00184     return ConnectInput(name, server_name);
00185 }
00186 
00187 bool JackMachSemaphore::Disconnect()
00188 {
00189         if (fSemaphore > 0) {
00190                 JackLog("JackMachSemaphore::Disconnect name = %s\n", fName);
00191                 fSemaphore = 0;
00192         }
00193     // Nothing to do
00194     return true;
00195 }
00196 
00197 // Server side : destroy the JackGlobals
00198 void JackMachSemaphore::Destroy()
00199 {
00200     kern_return_t res;
00201 
00202     if (fSemaphore > 0) {
00203         JackLog("JackMachSemaphore::Destroy\n");
00204         if ((res = semaphore_destroy(mach_task_self(), fSemaphore)) != KERN_SUCCESS) {
00205             jack_error("JackMachSemaphore::Destroy can't destroy semaphore err = %s", mach_error_string(res));
00206         }
00207         fSemaphore = 0;
00208     } else {
00209         jack_error("JackMachSemaphore::Destroy semaphore < 0");
00210     }
00211 }
00212 
00213 } // end of namespace
00214 

Generated on Thu Feb 14 11:16:02 2008 for Jackdmp by  doxygen 1.5.1