Jack2 1.9.6

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