diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2013-04-26 02:07:07 -0700 |
---|---|---|
committer | Patrick Ohly <patrick.ohly@intel.com> | 2013-05-06 17:21:35 +0200 |
commit | 4ad7eb49dc908b4dcd6e33fb53c3abcbd6eaa496 (patch) | |
tree | 52cf8d1d297d0913ecf6245863b1eb7ee120871a | |
parent | edee69694e91f1b038418829ba8c2721b8902eb5 (diff) |
Linux: allow overriding blocking pthread code
Blocking the main thread inside pthread_cond_(timed)wait() for long
periods of time is bad when that thread also needs to process events.
For example, in SyncEvolution the main thread must continue to check for
events on the glib event loop, otherwise the background thread can get stuck
in EDS and/or glib while waiting for that event processing.
As a stop-gap measure, export a function pointer that the user of the
Linux libsynthesis can override. The replacement must check for thread
completion and be able to use the mutex+condition variable for this,
so pass all of those as parameters.
A complete solution would be to define a plugable threading system
where the user of the library can replace the entire thread start/stop
with its own code.
-rwxr-xr-x | src/platform_adapters/unix_common/platform_thread.cpp | 68 | ||||
-rw-r--r-- | src/synthesis-linker.map | 2 |
2 files changed, 49 insertions, 21 deletions
diff --git a/src/platform_adapters/unix_common/platform_thread.cpp b/src/platform_adapters/unix_common/platform_thread.cpp index 06f1e20..f8c6208 100755 --- a/src/platform_adapters/unix_common/platform_thread.cpp +++ b/src/platform_adapters/unix_common/platform_thread.cpp @@ -154,6 +154,52 @@ void TThreadObject::kill(void) } } // TThreadObject::kill +static int CondTimedWait(pthread_cond_t *cond, pthread_mutex_t *mutex, bool &aTerminated, long aMilliSecondsToWait) +{ + int retval; + if (aMilliSecondsToWait<0) { + // wait indefinitely + retval= pthread_cond_wait(cond, mutex); + } + else { + // wait specified amount of time + struct timespec timeout; + + /* this conversion might be implemented in time module later */ + #define milli 1E-3 + #define msToLinearTimeFactor (secondToLinearTimeFactor*milli) // is usually 1 again + + lineartime_t ltm = getSystemNowAs(TCTX_UTC,NULL) - UnixToLineartimeOffset; // starting 1970 + ltm = (lineartime_t)(ltm/msToLinearTimeFactor); // as milliSeconds + ltm+= aMilliSecondsToWait; // add the offset from now + + timeout.tv_sec = (unsigned int)(ltm * milli); + timeout.tv_nsec= ( ltm % 1000 )*1000000; // ns + + retval= pthread_cond_timedwait(cond, mutex, &timeout); + } /* if */ + + return retval; +} + +extern "C" +{ + /** + * Wait until thread terminates or timeout occurs. + * + * Can use pthread_cond_[timed]wait with the given condition variable + * and mutex to be worken up by the terminating thread. However, aTerminated + * must be checked before each such pthread call, because the thread may + * already have signaled termination. + * + * If the implementation does not use pthread_cond_[timed]wait, then it + * must unlock the mutex. Otherwise the thread will never be able to lock + * it and set aTerminated. + * + * @param aMilliSecondsToWait < 0 for infinite wait, otherwise maximum time to wait since entering the function in ms + */ + int (*SySync_CondTimedWait)(pthread_cond_t *cond, pthread_mutex_t *mutex, bool &aTerminated, long aMilliSecondsToWait) = CondTimedWait; +} // waits for the thread to stop bool TThreadObject::waitfor(sInt32 aMilliSecondsToWait) @@ -165,27 +211,7 @@ bool TThreadObject::waitfor(sInt32 aMilliSecondsToWait) // wait for termination condition of the thread pthread_mutex_lock(&fDoneCondMutex); if (!fTerminated) { // catch also, if signalled already - if (aMilliSecondsToWait<0) { - // wait indefinitely - retval= pthread_cond_wait(&fDoneCond, &fDoneCondMutex); - } - else { - // wait specified amount of time - struct timespec timeout; - - /* this conversion might be implemented in time module later */ - #define milli 1E-3 - #define msToLinearTimeFactor (secondToLinearTimeFactor*milli) // is usually 1 again - - lineartime_t ltm = getSystemNowAs(TCTX_UTC,NULL) - UnixToLineartimeOffset; // starting 1970 - ltm = (lineartime_t)(ltm/msToLinearTimeFactor); // as milliSeconds - ltm+= aMilliSecondsToWait; // add the offset from now - - timeout.tv_sec = (unsigned int)(ltm * milli); - timeout.tv_nsec= ( ltm % 1000 )*1000000; // ns - - retval= pthread_cond_timedwait(&fDoneCond, &fDoneCondMutex, &timeout); - } /* if */ + retval= SySync_CondTimedWait(&fDoneCond, &fDoneCondMutex, fTerminated, aMilliSecondsToWait); } /* if */ pthread_mutex_unlock(&fDoneCondMutex); if (retval!=0) return false; // check if thread has completed => no, not yet diff --git a/src/synthesis-linker.map b/src/synthesis-linker.map index 224d8b2..580b85e 100644 --- a/src/synthesis-linker.map +++ b/src/synthesis-linker.map @@ -4,6 +4,8 @@ VER_1.0 { SySync_*ConnectEngineS; SySync_*DisconnectEngine; SySync_*ConsolePrintf; + SySync_CondTimedWait; + SySync_CondWait; extern "C++" { sysync::DataConversion*; sysync::SySyncDebugPuts*; |