Jack2 1.9.10

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 void JackMachSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size)
00030 {
00031     char ext_client_name[SYNC_MAX_NAME_SIZE + 1];
00032     JackTools::RewriteName(client_name, ext_client_name);
00033     snprintf(res, size, "jack_mach_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name);
00034 }
00035 
00036 bool JackMachSemaphore::Signal()
00037 {
00038     if (!fSemaphore) {
00039         jack_error("JackMachSemaphore::Signal name = %s already deallocated!!", fName);
00040         return false;
00041     }
00042 
00043     if (fFlush) {
00044         return true;
00045     }
00046 
00047     kern_return_t res;
00048     if ((res = semaphore_signal(fSemaphore)) != KERN_SUCCESS) {
00049         jack_error("JackMachSemaphore::Signal name = %s err = %s", fName, mach_error_string(res));
00050     }
00051     return (res == KERN_SUCCESS);
00052 }
00053 
00054 bool JackMachSemaphore::SignalAll()
00055 {
00056     if (!fSemaphore) {
00057         jack_error("JackMachSemaphore::SignalAll name = %s already deallocated!!", fName);
00058         return false;
00059     }
00060 
00061     if (fFlush) {
00062         return true;
00063     }
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 deallocated!!", 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 deallocated!!", 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, sizeof(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, sizeof(fName));
00153     kern_return_t res;
00154 
00155     if (fBootPort == 0) {
00156         if ((res = task_get_bootstrap_port(mach_task_self(), &fBootPort)) != KERN_SUCCESS) {
00157             jack_error("Connect: can't find bootstrap port err = %s", mach_error_string(res));
00158             return false;
00159         }
00160     }
00161 
00162     if ((res = bootstrap_look_up(fBootPort, fName, &fSemaphore)) != KERN_SUCCESS) {
00163         jack_error("Connect: can't find mach semaphore name = %s err = %s", fName, mach_error_string(res));
00164         return false;
00165     }
00166 
00167     jack_log("JackMachSemaphore::Connect name = %s ", fName);
00168     return true;
00169 }
00170 
00171 bool JackMachSemaphore::Connect(const char* name, const char* server_name)
00172 {
00173     return ConnectInput(name, server_name);
00174 }
00175 
00176 bool JackMachSemaphore::ConnectOutput(const char* name, const char* server_name)
00177 {
00178     return ConnectInput(name, server_name);
00179 }
00180 
00181 bool JackMachSemaphore::Disconnect()
00182 {
00183     if (fSemaphore > 0) {
00184         jack_log("JackMachSemaphore::Disconnect name = %s", fName);
00185         fSemaphore = 0;
00186     }
00187     // Nothing to do
00188     return true;
00189 }
00190 
00191 // Server side : destroy the JackGlobals
00192 void JackMachSemaphore::Destroy()
00193 {
00194     kern_return_t res;
00195 
00196     if (fSemaphore > 0) {
00197         jack_log("JackMachSemaphore::Destroy name = %s", fName);
00198         if ((res = semaphore_destroy(mach_task_self(), fSemaphore)) != KERN_SUCCESS) {
00199             jack_error("JackMachSemaphore::Destroy can't destroy semaphore err = %s", mach_error_string(res));
00200         }
00201         fSemaphore = 0;
00202     } else {
00203         jack_error("JackMachSemaphore::Destroy semaphore < 0");
00204     }
00205 }
00206 
00207 } // end of namespace
00208