summaryrefslogtreecommitdiff
path: root/src/Fl_lock.cxx
diff options
context:
space:
mode:
authorNo Author <No Author>2001-08-01 21:24:49 +0000
committerNo Author <No Author>2001-08-01 21:24:49 +0000
commit3cb5ebe0e811f3db008085d985b7761725589a74 (patch)
tree0a7184a5f02fffe927af911758f3a9a4a2f4a37e /src/Fl_lock.cxx
parent4477e166400f197bed50b09e01e695221cde96b6 (diff)
This commit was manufactured by cvs2svn to create branch 'branch-1.1'.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@1513 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_lock.cxx')
-rw-r--r--src/Fl_lock.cxx145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/Fl_lock.cxx b/src/Fl_lock.cxx
new file mode 100644
index 000000000..ebd8b420f
--- /dev/null
+++ b/src/Fl_lock.cxx
@@ -0,0 +1,145 @@
+/* Fl_Lock.cxx
+
+ I would prefer that fltk contain the minimal amount of extra stuff
+ for doing threads. There are other portable thread wrapper libraries
+ out there and fltk should not be providing another. This file
+ is an attempt to make minimal additions and make them self-contained
+ in this source file.
+
+ Fl::lock() - recursive lock. Plus you must call this before the
+ first call to Fl::wait()/run() to initialize the thread system.
+ The lock is locked all the time except when Fl::wait() is waiting
+ for events.
+
+ Fl::unlock() - release the recursive lock.
+
+ Fl::awake(void*) - Causes Fl::wait() to return (with the lock locked)
+ even if there are no events ready.
+
+ Fl::thread_message() - returns an argument sent to an Fl::awake call,
+ or returns null if none. Warning: the current implementation only
+ has a one-entry queue and only returns the most recent value!
+
+ See also the Fl_Threads.h header file, which provides convienence
+ functions so you can create your own threads and mutexes.
+*/
+
+#include <fltk/Fl.h>
+#include <config.h>
+
+////////////////////////////////////////////////////////////////
+#if defined(_WIN32)
+
+#include <windows.h>
+#include <process.h>
+
+// these pointers are in Fl_win32.cxx:
+extern void (*fl_lock_function)();
+extern void (*fl_unlock_function)();
+
+static DWORD main_thread;
+
+CRITICAL_SECTION cs;
+
+static void unlock_function() {
+ LeaveCriticalSection(&cs);
+}
+
+static void lock_function() {
+ EnterCriticalSection(&cs);
+}
+
+void Fl::lock() {
+ if (!main_thread)
+ InitializeCriticalSection(&cs);
+ lock_function();
+ if (!main_thread) {
+ fl_lock_function = lock_function;
+ fl_unlock_function = unlock_function;
+ main_thread = GetCurrentThreadId();
+ }
+}
+
+void Fl::unlock() {
+ unlock_function();
+}
+
+// when called from a thread, it causes FLTK to awake from Fl::wait()
+void Fl::awake(void* msg) {
+ PostThreadMessage( main_thread, WM_USER, (WPARAM)msg, 0);
+}
+
+////////////////////////////////////////////////////////////////
+#elif HAVE_PTHREAD
+#include <unistd.h>
+#include <pthread.h>
+
+#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+// Linux supports recursive locks, use them directly:
+
+static pthread_mutex_t fltk_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+
+static void lock_function() {
+ pthread_mutex_lock(&fltk_mutex);
+}
+
+void Fl::unlock() {
+ pthread_mutex_unlock(&fltk_mutex);
+}
+
+// this is needed for the Fl_Mutex constructor:
+pthread_mutexattr_t Fl_Mutex_attrib = {PTHREAD_MUTEX_RECURSIVE_NP};
+
+#else
+// Make a recursive lock out of the pthread mutex:
+
+static pthread_mutex_t fltk_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_t owner;
+static int counter;
+
+static void lock_function() {
+ if (!counter || owner != pthread_self()) {
+ pthread_mutex_lock(&fltk_mutex); owner = pthread_self();
+ }
+ counter++;
+}
+
+void Fl::unlock() {
+ if (!--counter) pthread_mutex_unlock(&fltk_mutex);
+}
+
+#endif
+
+static int thread_filedes[2];
+
+// these pointers are in Fl_x.cxx:
+extern void (*fl_lock_function)();
+extern void (*fl_unlock_function)();
+
+static void* thread_message_;
+void* Fl::thread_message() {
+ void* r = thread_message_;
+ thread_message_ = 0;
+ return r;
+}
+
+static void thread_awake_cb(int fd, void*) {
+ read(fd, &thread_message_, sizeof(void*));
+}
+
+void Fl::lock() {
+ lock_function();
+ if (!thread_filedes[1]) { // initialize the mt support
+ // Init threads communication pipe to let threads awake FLTK from wait
+ pipe(thread_filedes);
+ Fl::add_fd(thread_filedes[0], FL_READ, thread_awake_cb);
+ fl_lock_function = lock_function;
+ fl_unlock_function = Fl::unlock;
+ }
+}
+
+void Fl::awake(void* msg) {
+ write(thread_filedes[1], &msg, sizeof(void*));
+}
+
+#endif