/* Copyright (C) 2004-2005 Grame This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "JackPthreadCond.h" #include "JackError.h" namespace Jack { JackPthreadCondArray* JackPthreadCondServer::fTable = NULL; long JackPthreadCondServer::fCount = 0; JackShmReadWritePtr1 JackPthreadCondClient::fTable; long JackPthreadCondClient::fCount = 0; JackPthreadCondArray::JackPthreadCondArray() { for (int i = 0; i < MAX_ITEM; i++) { strcpy(fTable[i].fName, ""); } } void JackPthreadCond::BuildName(const char* name, char* res) { sprintf(res, "%s/jack_sem.%s", jack_client_dir, name); } bool JackPthreadCond::Signal() { //pthread_mutex_lock(&fSynchro->fLock); //JackLog("JackPthreadCond::Signal...\n"); pthread_cond_signal(&fSynchro->fCond); //pthread_mutex_unlock(&fSynchro->fLock); return true; } bool JackPthreadCond::SignalAll() { pthread_cond_broadcast(&fSynchro->fCond); return true; } bool JackPthreadCond::Wait() { pthread_mutex_lock(&fSynchro->fLock); //JackLog("JackPthreadCond::Wait...\n"); pthread_cond_wait(&fSynchro->fCond, &fSynchro->fLock); pthread_mutex_unlock(&fSynchro->fLock); //JackLog("JackProcessSync::Wait finished\n"); return true; } bool JackPthreadCond::TimedWait(long usec) { timespec time; struct timeval now; gettimeofday(&now, 0); time.tv_sec = now.tv_sec + usec / 1000000; time.tv_nsec = (now.tv_usec + (usec % 1000000)) * 1000; pthread_mutex_lock(&fSynchro->fLock); JackLog("JackProcessSync::Wait...\n"); pthread_cond_timedwait(&fSynchro->fCond, &fSynchro->fLock, &time); pthread_mutex_unlock(&fSynchro->fLock); JackLog("JackProcessSync::Wait finished\n"); return true; } // Client side : get the published semaphore from server bool JackPthreadCond::ConnectInput(const char* name) { BuildName(name, fName); JackLog("JackPthreadCond::Connect %s\n", fName); // Temporary... if (fSynchro) { JackLog("Already connected name = %s\n", name); return true; } for (int i = 0; i < MAX_ITEM; i++) { JackPthreadCondItem* synchro = &(GetTable()->fTable[i]); if (strcmp(fName, synchro->fName) == 0) { fSynchro = synchro; return true; } } return false; } bool JackPthreadCond::Connect(const char* name) { return ConnectInput(name); } bool JackPthreadCond::ConnectOutput(const char* name) { return ConnectInput(name); } bool JackPthreadCond::Disconnect() { JackLog("JackPthreadCond::Disconnect %s\n", fName); if (fSynchro) { strcpy(fSynchro->fName, ""); fSynchro = NULL; return true; } else { return false; } } JackPthreadCondServer::JackPthreadCondServer(): JackPthreadCond() { if (fCount++ == 0 && !fTable) { fTable = new JackPthreadCondArray(); } if (fCount == MAX_ITEM) throw new std::bad_alloc; } JackPthreadCondServer::~JackPthreadCondServer() { if (--fCount == 0 && fTable) { delete fTable; fTable = NULL; } } bool JackPthreadCondServer::Allocate(const char* name, int value) { BuildName(name, fName); JackLog("JackPthreadCond::Allocate name = %s val = %ld\n", fName, value); pthread_mutexattr_t mutex_attr; pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL); pthread_condattr_t cond_attr; pthread_condattr_init(&cond_attr); pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); for (int i = 0; i < MAX_ITEM; i++) { if (strcmp(fTable->fTable[i].fName, "") == 0) { // first empty place fSynchro = &fTable->fTable[i]; if (pthread_mutex_init(&fSynchro->fLock, &mutex_attr) != 0) { jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno)); return false; } if (pthread_cond_init(&fSynchro->fCond, &cond_attr) != 0) { jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno)); return false; } strcpy(fSynchro->fName, fName); return true; } } return false; } void JackPthreadCondServer::Destroy() { if (fSynchro != NULL) { pthread_mutex_destroy(&fSynchro->fLock); pthread_cond_destroy(&fSynchro->fCond); strcpy(fSynchro->fName, ""); fSynchro = NULL; } else { jack_error("JackPthreadCond::Destroy semaphore == NULL"); } } JackPthreadCondClient::JackPthreadCondClient(int shared_index): JackPthreadCond() { if (fCount++ == 0 && !fTable) { fTable = shared_index; } if (fCount == MAX_ITEM) throw new std::bad_alloc; } JackPthreadCondClient::~JackPthreadCondClient() { if (--fCount == 0 && fTable) delete fTable; } } // end of namespace