git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4744 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.9.5
| @@ -36,6 +36,10 @@ John Emmas | |||||
| Jackdmp changes log | Jackdmp changes log | ||||
| --------------------------- | --------------------------- | ||||
| 2012-01-29 Stephane Letz <letz@grame.fr> | |||||
| * A bit more robust JackMessageBuffer implementation (in progress). | |||||
| 2012-01-27 Stephane Letz <letz@grame.fr> | 2012-01-27 Stephane Letz <letz@grame.fr> | ||||
| * Rename JackProcessSync in JackPosixProcessSync. | * Rename JackProcessSync in JackPosixProcessSync. | ||||
| @@ -63,7 +63,9 @@ struct JackLibGlobals | |||||
| JackLibGlobals() | JackLibGlobals() | ||||
| { | { | ||||
| jack_log("JackLibGlobals"); | jack_log("JackLibGlobals"); | ||||
| JackMessageBuffer::Create(); | |||||
| if (!JackMessageBuffer::Create()) { | |||||
| jack_error("Cannot create message buffer"); | |||||
| } | |||||
| fGraphManager = -1; | fGraphManager = -1; | ||||
| fEngineControl = -1; | fEngineControl = -1; | ||||
| @@ -42,13 +42,13 @@ JackMessageBuffer::JackMessageBuffer() | |||||
| JackMessageBuffer::~JackMessageBuffer() | JackMessageBuffer::~JackMessageBuffer() | ||||
| {} | {} | ||||
| void JackMessageBuffer::Start() | |||||
| bool JackMessageBuffer::Start() | |||||
| { | { | ||||
| fRunning = true; | fRunning = true; | ||||
| fThread.StartSync(); | |||||
| return fThread.StartSync(); | |||||
| } | } | ||||
| void JackMessageBuffer::Stop() | |||||
| bool JackMessageBuffer::Stop() | |||||
| { | { | ||||
| if (fOverruns > 0) { | if (fOverruns > 0) { | ||||
| jack_error("WARNING: %d message buffer overruns!", fOverruns); | jack_error("WARNING: %d message buffer overruns!", fOverruns); | ||||
| @@ -66,6 +66,7 @@ void JackMessageBuffer::Stop() | |||||
| } | } | ||||
| Flush(); | Flush(); | ||||
| return true; | |||||
| } | } | ||||
| void JackMessageBuffer::Flush() | void JackMessageBuffer::Flush() | ||||
| @@ -117,20 +118,30 @@ bool JackMessageBuffer::Execute() | |||||
| return false; | return false; | ||||
| } | } | ||||
| void JackMessageBuffer::Create() | |||||
| bool JackMessageBuffer::Create() | |||||
| { | { | ||||
| if (fInstance == NULL) { | if (fInstance == NULL) { | ||||
| fInstance = new JackMessageBuffer(); | fInstance = new JackMessageBuffer(); | ||||
| fInstance->Start(); | |||||
| if (!fInstance->Start()) { | |||||
| jack_error("JackMessageBuffer::Create cannot start thread..."); | |||||
| delete fInstance; | |||||
| fInstance = NULL; | |||||
| return false; | |||||
| } | |||||
| } | } | ||||
| return true; | |||||
| } | } | ||||
| void JackMessageBuffer::Destroy() | |||||
| bool JackMessageBuffer::Destroy() | |||||
| { | { | ||||
| if (fInstance != NULL) { | if (fInstance != NULL) { | ||||
| fInstance->Stop(); | fInstance->Stop(); | ||||
| delete fInstance; | delete fInstance; | ||||
| fInstance = NULL; | fInstance = NULL; | ||||
| return true; | |||||
| } else { | |||||
| return false; | |||||
| } | } | ||||
| } | } | ||||
| @@ -146,7 +157,7 @@ void JackMessageBufferAdd(int level, const char *message) | |||||
| void JackMessageBuffer::SetInitCallback(JackThreadInitCallback callback, void *arg) | void JackMessageBuffer::SetInitCallback(JackThreadInitCallback callback, void *arg) | ||||
| { | { | ||||
| if (fGuard.Lock()) { | |||||
| if (fInstance && fGuard.Lock()) { | |||||
| /* set up the callback */ | /* set up the callback */ | ||||
| fInitArg = arg; | fInitArg = arg; | ||||
| fInit = callback; | fInit = callback; | ||||
| @@ -157,7 +168,7 @@ void JackMessageBuffer::SetInitCallback(JackThreadInitCallback callback, void *a | |||||
| /* and we're done */ | /* and we're done */ | ||||
| fGuard.Unlock(); | fGuard.Unlock(); | ||||
| } else { | } else { | ||||
| jack_error("JackMessageBuffer::SetInitCallback lock cannot be taken"); | |||||
| jack_error("JackMessageBuffer::SetInitCallback : callback cannot be executed"); | |||||
| } | } | ||||
| } | } | ||||
| @@ -69,8 +69,8 @@ class JackMessageBuffer : public JackRunnableInterface | |||||
| void Flush(); | void Flush(); | ||||
| void Start(); | |||||
| void Stop(); | |||||
| bool Start(); | |||||
| bool Stop(); | |||||
| public: | public: | ||||
| @@ -80,8 +80,8 @@ class JackMessageBuffer : public JackRunnableInterface | |||||
| // JackRunnableInterface interface | // JackRunnableInterface interface | ||||
| bool Execute(); | bool Execute(); | ||||
| void static Create(); | |||||
| void static Destroy(); | |||||
| bool static Create(); | |||||
| bool static Destroy(); | |||||
| void AddMessage(int level, const char *message); | void AddMessage(int level, const char *message); | ||||
| void SetInitCallback(JackThreadInitCallback callback, void *arg); | void SetInitCallback(JackThreadInitCallback callback, void *arg); | ||||
| @@ -78,7 +78,9 @@ JackServer::~JackServer() | |||||
| int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) | int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) | ||||
| { | { | ||||
| // TODO: move that in reworked JackServerGlobals::Init() | // TODO: move that in reworked JackServerGlobals::Init() | ||||
| JackMessageBuffer::Create(); | |||||
| if (!JackMessageBuffer::Create()) { | |||||
| jack_error("Cannot create message buffer"); | |||||
| } | |||||
| if ((fAudioDriver = fDriverInfo->Open(driver_desc, fEngine, GetSynchroTable(), driver_params)) == NULL) { | if ((fAudioDriver = fDriverInfo->Open(driver_desc, fEngine, GetSynchroTable(), driver_params)) == NULL) { | ||||
| jack_error("Cannot initialize driver"); | jack_error("Cannot initialize driver"); | ||||
| @@ -26,43 +26,51 @@ namespace Jack | |||||
| void JackPosixProcessSync::Signal() | void JackPosixProcessSync::Signal() | ||||
| { | { | ||||
| int res = pthread_cond_signal(&fCond); | int res = pthread_cond_signal(&fCond); | ||||
| if (res != 0) | |||||
| if (res != 0) { | |||||
| jack_error("JackPosixProcessSync::Signal error err = %s", strerror(res)); | jack_error("JackPosixProcessSync::Signal error err = %s", strerror(res)); | ||||
| } | |||||
| } | } | ||||
| // TO DO : check thread consistency? | // TO DO : check thread consistency? | ||||
| void JackPosixProcessSync::LockedSignal() | void JackPosixProcessSync::LockedSignal() | ||||
| { | { | ||||
| int res = pthread_mutex_lock(&fMutex); | int res = pthread_mutex_lock(&fMutex); | ||||
| if (res != 0) | |||||
| if (res != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedSignal error err = %s", strerror(res)); | jack_error("JackPosixProcessSync::LockedSignal error err = %s", strerror(res)); | ||||
| } | |||||
| res = pthread_cond_signal(&fCond); | res = pthread_cond_signal(&fCond); | ||||
| if (res != 0) | |||||
| if (res != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedSignal error err = %s", strerror(res)); | jack_error("JackPosixProcessSync::LockedSignal error err = %s", strerror(res)); | ||||
| } | |||||
| res = pthread_mutex_unlock(&fMutex); | res = pthread_mutex_unlock(&fMutex); | ||||
| if (res != 0) | |||||
| if (res != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedSignal error err = %s", strerror(res)); | jack_error("JackPosixProcessSync::LockedSignal error err = %s", strerror(res)); | ||||
| } | |||||
| } | } | ||||
| void JackPosixProcessSync::SignalAll() | void JackPosixProcessSync::SignalAll() | ||||
| { | { | ||||
| int res = pthread_cond_broadcast(&fCond); | int res = pthread_cond_broadcast(&fCond); | ||||
| if (res != 0) | |||||
| if (res != 0) { | |||||
| jack_error("JackPosixProcessSync::SignalAll error err = %s", strerror(res)); | jack_error("JackPosixProcessSync::SignalAll error err = %s", strerror(res)); | ||||
| } | |||||
| } | } | ||||
| // TO DO : check thread consistency? | // TO DO : check thread consistency? | ||||
| void JackPosixProcessSync::LockedSignalAll() | void JackPosixProcessSync::LockedSignalAll() | ||||
| { | { | ||||
| int res = pthread_mutex_lock(&fMutex); | int res = pthread_mutex_lock(&fMutex); | ||||
| if (res != 0) | |||||
| if (res != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedSignalAll error err = %s", strerror(res)); | jack_error("JackPosixProcessSync::LockedSignalAll error err = %s", strerror(res)); | ||||
| } | |||||
| res = pthread_cond_broadcast(&fCond); | res = pthread_cond_broadcast(&fCond); | ||||
| if (res != 0) | |||||
| if (res != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedSignalAll error err = %s", strerror(res)); | jack_error("JackPosixProcessSync::LockedSignalAll error err = %s", strerror(res)); | ||||
| } | |||||
| res = pthread_mutex_unlock(&fMutex); | res = pthread_mutex_unlock(&fMutex); | ||||
| if (res != 0) | |||||
| if (res != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedSignalAll error err = %s", strerror(res)); | jack_error("JackPosixProcessSync::LockedSignalAll error err = %s", strerror(res)); | ||||
| } | |||||
| } | } | ||||
| void JackPosixProcessSync::Wait() | void JackPosixProcessSync::Wait() | ||||
| @@ -83,13 +91,16 @@ void JackPosixProcessSync::LockedWait() | |||||
| { | { | ||||
| int res; | int res; | ||||
| res = pthread_mutex_lock(&fMutex); | res = pthread_mutex_lock(&fMutex); | ||||
| if (res != 0) | |||||
| if (res != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedWait error err = %s", strerror(res)); | jack_error("JackPosixProcessSync::LockedWait error err = %s", strerror(res)); | ||||
| if ((res = pthread_cond_wait(&fCond, &fMutex)) != 0) | |||||
| } | |||||
| if ((res = pthread_cond_wait(&fCond, &fMutex)) != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedWait error err = %s", strerror(res)); | jack_error("JackPosixProcessSync::LockedWait error err = %s", strerror(res)); | ||||
| } | |||||
| res = pthread_mutex_unlock(&fMutex); | res = pthread_mutex_unlock(&fMutex); | ||||
| if (res != 0) | |||||
| if (res != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedWait error err = %s", strerror(res)); | jack_error("JackPosixProcessSync::LockedWait error err = %s", strerror(res)); | ||||
| } | |||||
| } | } | ||||
| bool JackPosixProcessSync::TimedWait(long usec) | bool JackPosixProcessSync::TimedWait(long usec) | ||||
| @@ -133,8 +144,9 @@ bool JackPosixProcessSync::LockedTimedWait(long usec) | |||||
| int res1, res2; | int res1, res2; | ||||
| res1 = pthread_mutex_lock(&fMutex); | res1 = pthread_mutex_lock(&fMutex); | ||||
| if (res1 != 0) | |||||
| if (res1 != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedTimedWait error err = %s", usec, strerror(res1)); | jack_error("JackPosixProcessSync::LockedTimedWait error err = %s", usec, strerror(res1)); | ||||
| } | |||||
| jack_log("JackPosixProcessSync::TimedWait time out = %ld", usec); | jack_log("JackPosixProcessSync::TimedWait time out = %ld", usec); | ||||
| gettimeofday(&T0, 0); | gettimeofday(&T0, 0); | ||||
| @@ -144,13 +156,15 @@ bool JackPosixProcessSync::LockedTimedWait(long usec) | |||||
| time.tv_sec = now.tv_sec + (next_date_usec / 1000000); | time.tv_sec = now.tv_sec + (next_date_usec / 1000000); | ||||
| time.tv_nsec = (next_date_usec % 1000000) * 1000; | time.tv_nsec = (next_date_usec % 1000000) * 1000; | ||||
| res2 = pthread_cond_timedwait(&fCond, &fMutex, &time); | res2 = pthread_cond_timedwait(&fCond, &fMutex, &time); | ||||
| if (res2 != 0) | |||||
| if (res2 != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedTimedWait error usec = %ld err = %s", usec, strerror(res2)); | jack_error("JackPosixProcessSync::LockedTimedWait error usec = %ld err = %s", usec, strerror(res2)); | ||||
| } | |||||
| gettimeofday(&T1, 0); | gettimeofday(&T1, 0); | ||||
| res1 = pthread_mutex_unlock(&fMutex); | res1 = pthread_mutex_unlock(&fMutex); | ||||
| if (res1 != 0) | |||||
| if (res1 != 0) { | |||||
| jack_error("JackPosixProcessSync::LockedTimedWait error err = %s", usec, strerror(res1)); | jack_error("JackPosixProcessSync::LockedTimedWait error err = %s", usec, strerror(res1)); | ||||
| } | |||||
| jack_log("JackPosixProcessSync::TimedWait finished delta = %5.1lf", | jack_log("JackPosixProcessSync::TimedWait finished delta = %5.1lf", | ||||
| (1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec)); | (1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec)); | ||||
| @@ -25,28 +25,36 @@ namespace Jack | |||||
| void JackWinProcessSync::Signal() | void JackWinProcessSync::Signal() | ||||
| { | { | ||||
| SetEvent(fEvent); | |||||
| if (!SetEvent(fEvent)) { | |||||
| jack_error("JackWinProcessSync::Signal SetEvent err = %d", GetLastError()); | |||||
| } | |||||
| } | } | ||||
| void JackWinProcessSync::LockedSignal() | void JackWinProcessSync::LockedSignal() | ||||
| { | { | ||||
| WaitForSingleObject(fMutex, INFINITE); | |||||
| SetEvent(fEvent); | |||||
| ReleaseMutex(fMutex); | |||||
| DWORD res = WaitForSingleObject(fMutex, INFINITE); | |||||
| if (res != WAIT_OBJECT_0) { | |||||
| jack_error("JackWinProcessSync::LockedSignal WaitForSingleObject err = %d", GetLastError()); | |||||
| } | |||||
| if (!SetEvent(fEvent)) { | |||||
| jack_error("JackWinProcessSync::LockedSignal SetEvent err = %d", GetLastError()); | |||||
| } | |||||
| if (!ReleaseMutex(fMutex)) { | |||||
| jack_error("JackWinProcessSync::LockedSignal ReleaseMutex err = %d", GetLastError()); | |||||
| } | |||||
| } | } | ||||
| void JackWinProcessSync::SignalAll() | void JackWinProcessSync::SignalAll() | ||||
| { | { | ||||
| SetEvent(fEvent); | |||||
| Signal(); | |||||
| } | } | ||||
| void JackWinProcessSync::LockedSignalAll() | void JackWinProcessSync::LockedSignalAll() | ||||
| { | { | ||||
| WaitForSingleObject(fMutex, INFINITE); | |||||
| SetEvent(fEvent); | |||||
| ReleaseMutex(fMutex); | |||||
| LockedSignal(); | |||||
| } | } | ||||
| /* | /* | ||||
| void JackWinProcessSync::Wait() | void JackWinProcessSync::Wait() | ||||
| { | { | ||||
| @@ -75,43 +83,65 @@ bool JackWinProcessSync::LockedTimedWait(long usec) | |||||
| */ | */ | ||||
| // Code from APPLE CAGuard.cpp : does not seem to work as expected... | // Code from APPLE CAGuard.cpp : does not seem to work as expected... | ||||
| void JackWinProcessSync::Wait() | void JackWinProcessSync::Wait() | ||||
| { | { | ||||
| ReleaseMutex(fMutex); | |||||
| HANDLE handles[] = { fMutex, fEvent }; | |||||
| DWORD res = WaitForMultipleObjects(2, handles, true, INFINITE); | |||||
| if (res != WAIT_OBJECT_0) | |||||
| jack_error("Wait error err = %d", GetLastError()); | |||||
| ResetEvent(fEvent); | |||||
| if (!ReleaseMutex(fMutex)) { | |||||
| jack_error("JackWinProcessSync::Wait ReleaseMutex err = %d", GetLastError()); | |||||
| } | |||||
| DWORD res = WaitForSingleObject(fEvent, INFINITE); | |||||
| if (res != WAIT_OBJECT_0) { | |||||
| jack_error("JackWinProcessSync::Wait WaitForSingleObject err = %d", GetLastError()); | |||||
| } | |||||
| } | } | ||||
| void JackWinProcessSync::LockedWait() | void JackWinProcessSync::LockedWait() | ||||
| { | { | ||||
| // Does it make sense on Windows, use non-locked version for now... | |||||
| Wait(); | |||||
| if (!ReleaseMutex(fMutex)) { | |||||
| jack_error("JackWinProcessSync::LockedWait ReleaseMutex err = %d", GetLastError()); | |||||
| } | |||||
| HANDLE handles[] = { fMutex, fEvent }; | |||||
| DWORD res = WaitForMultipleObjects(2, handles, true, INFINITE); | |||||
| if (res != WAIT_OBJECT_0) { | |||||
| jack_error("JackWinProcessSync::LockedWait WaitForMultipleObjects err = %d", GetLastError()); | |||||
| } | |||||
| if (!ResetEvent(fEvent)) { | |||||
| jack_error("JackWinProcessSync::LockedWait ResetEvent err = %d", GetLastError()); | |||||
| } | |||||
| } | } | ||||
| bool JackWinProcessSync::TimedWait(long usec) | bool JackWinProcessSync::TimedWait(long usec) | ||||
| { | { | ||||
| ReleaseMutex(fMutex); | |||||
| HANDLE handles[] = { fMutex, fEvent }; | |||||
| DWORD res = WaitForMultipleObjects(2, handles, true, usec / 1000); | |||||
| if ((res != WAIT_OBJECT_0) && (res != WAIT_TIMEOUT)) | |||||
| jack_error("TimedWait error err = %d", GetLastError()); | |||||
| ResetEvent(fEvent); | |||||
| return (res == WAIT_OBJECT_0); | |||||
| if (!ReleaseMutex(fMutex)) { | |||||
| jack_error("JackWinProcessSync::TimedWait ReleaseMutex err = %d", GetLastError()); | |||||
| } | |||||
| DWORD res = WaitForSingleObject(fEvent, usec / 1000); | |||||
| if (res != WAIT_OBJECT_0) { | |||||
| jack_error("JackWinProcessSync::TimedWait WaitForSingleObject err = %d", GetLastError()); | |||||
| } | |||||
| return (res == WAIT_OBJECT_0); | |||||
| } | } | ||||
| bool JackWinProcessSync::LockedTimedWait(long usec) | bool JackWinProcessSync::LockedTimedWait(long usec) | ||||
| { | { | ||||
| // Does it make sense on Windows, use non-locked version for now... | |||||
| //return TimedWait(usec); | |||||
| bool res = TimedWait(usec); | |||||
| if (!res) | |||||
| jack_error("LockedTimedWait error usec = %d", usec); | |||||
| return res; | |||||
| if (!ReleaseMutex(fMutex)) { | |||||
| jack_error("JackWinProcessSync::LockedTimedWait ReleaseMutex err = %d", GetLastError()); | |||||
| } | |||||
| HANDLE handles[] = { fMutex, fEvent }; | |||||
| DWORD res = WaitForMultipleObjects(2, handles, true, usec / 1000); | |||||
| if ((res != WAIT_OBJECT_0) && (res != WAIT_TIMEOUT)) | |||||
| jack_error("ackWinProcessSync::LockedTimedWait WaitForMultipleObjects err = %d", GetLastError()); | |||||
| if (!ResetEvent(fEvent)) { | |||||
| jack_error("JackWinProcessSync::LockedTimedWait ResetEvent err = %d", GetLastError()); | |||||
| } | |||||
| return (res == WAIT_OBJECT_0); | |||||
| } | } | ||||