summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2013-04-26 02:07:07 -0700
committerPatrick Ohly <patrick.ohly@intel.com>2013-05-06 17:21:35 +0200
commit4ad7eb49dc908b4dcd6e33fb53c3abcbd6eaa496 (patch)
tree52cf8d1d297d0913ecf6245863b1eb7ee120871a
parentedee69694e91f1b038418829ba8c2721b8902eb5 (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-xsrc/platform_adapters/unix_common/platform_thread.cpp68
-rw-r--r--src/synthesis-linker.map2
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*;