summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2021-02-16 16:28:44 +0100
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2021-02-16 16:28:57 +0100
commit9fdd675eab7cae04dc176ea2aba2d53c59101beb (patch)
treecb291e89411d0b73a74a3259fd651caccd0c405f /src/drivers
parentb709b2a2d3451ec48d454a895a459dadf7c184e5 (diff)
Remove FL_CFG_SYS_POSIX and FL_CFG_SYS_WIN32 preprocessor vars from Fl_lock.cxx
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/Posix/Fl_Posix_System_Driver.H6
-rw-r--r--src/drivers/Posix/Fl_Posix_System_Driver.cxx150
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_System_Driver.H4
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx67
4 files changed, 224 insertions, 3 deletions
diff --git a/src/drivers/Posix/Fl_Posix_System_Driver.H b/src/drivers/Posix/Fl_Posix_System_Driver.H
index e077e490f..52c138260 100644
--- a/src/drivers/Posix/Fl_Posix_System_Driver.H
+++ b/src/drivers/Posix/Fl_Posix_System_Driver.H
@@ -2,7 +2,7 @@
// Definition of POSIX system driver
// for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2010-2020 by Bill Spitzak and others.
+// Copyright 2010-2021 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -79,6 +79,10 @@ public:
virtual int dot_file_hidden() {return 1;}
virtual void gettime(time_t *sec, int *usec);
virtual char* strdup(const char *s) {return ::strdup(s);}
+#if defined(HAVE_PTHREAD)
+ virtual void lock_ring();
+ virtual void unlock_ring();
+#endif
};
#endif // FL_POSIX_SYSTEM_DRIVER_H
diff --git a/src/drivers/Posix/Fl_Posix_System_Driver.cxx b/src/drivers/Posix/Fl_Posix_System_Driver.cxx
index 75df02e7a..633794a86 100644
--- a/src/drivers/Posix/Fl_Posix_System_Driver.cxx
+++ b/src/drivers/Posix/Fl_Posix_System_Driver.cxx
@@ -171,3 +171,153 @@ int Fl_Posix_System_Driver::run_program(const char *program, char **argv, char *
// Return indicating success...
return 1;
}
+
+////////////////////////////////////////////////////////////////
+// POSIX threading...
+#if defined(HAVE_PTHREAD)
+# include <unistd.h>
+# include <fcntl.h>
+# include <pthread.h>
+
+// Pipe for thread messaging via Fl::awake()...
+static int thread_filedes[2];
+
+// Mutex and state information for Fl::lock() and Fl::unlock()...
+static pthread_mutex_t fltk_mutex;
+static pthread_t owner;
+static int counter;
+
+static void lock_function_init_std() {
+ pthread_mutex_init(&fltk_mutex, NULL);
+}
+
+static void lock_function_std() {
+ if (!counter || owner != pthread_self()) {
+ pthread_mutex_lock(&fltk_mutex);
+ owner = pthread_self();
+ }
+ counter++;
+}
+
+static void unlock_function_std() {
+ if (!--counter) pthread_mutex_unlock(&fltk_mutex);
+}
+
+# ifdef PTHREAD_MUTEX_RECURSIVE
+static bool lock_function_init_rec() {
+ pthread_mutexattr_t attrib;
+ pthread_mutexattr_init(&attrib);
+ if (pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE)) {
+ pthread_mutexattr_destroy(&attrib);
+ return true;
+ }
+
+ pthread_mutex_init(&fltk_mutex, &attrib);
+ return false;
+}
+
+static void lock_function_rec() {
+ pthread_mutex_lock(&fltk_mutex);
+}
+
+static void unlock_function_rec() {
+ pthread_mutex_unlock(&fltk_mutex);
+}
+# endif // PTHREAD_MUTEX_RECURSIVE
+
+void Fl_Posix_System_Driver::awake(void* msg) {
+ if (thread_filedes[1]) {
+ if (write(thread_filedes[1], &msg, sizeof(void*))==0) { /* ignore */ }
+ }
+}
+
+static void* thread_message_;
+void* Fl_Posix_System_Driver::thread_message() {
+ void* r = thread_message_;
+ thread_message_ = 0;
+ return r;
+}
+
+static void thread_awake_cb(int fd, void*) {
+ if (read(fd, &thread_message_, sizeof(void*))==0) {
+ /* This should never happen */
+ }
+ Fl_Awake_Handler func;
+ void *data;
+ while (Fl::get_awake_handler_(func, data)==0) {
+ (*func)(data);
+ }
+}
+
+// These pointers are in Fl_x.cxx:
+extern void (*fl_lock_function)();
+extern void (*fl_unlock_function)();
+
+int Fl_Posix_System_Driver::lock() {
+ if (!thread_filedes[1]) {
+ // Initialize thread communication pipe to let threads awake FLTK
+ // from Fl::wait()
+ if (pipe(thread_filedes)==-1) {
+ /* this should not happen */
+ }
+
+ // Make the write side of the pipe non-blocking to avoid deadlock
+ // conditions (STR #1537)
+ fcntl(thread_filedes[1], F_SETFL,
+ fcntl(thread_filedes[1], F_GETFL) | O_NONBLOCK);
+
+ // Monitor the read side of the pipe so that messages sent via
+ // Fl::awake() from a thread will "wake up" the main thread in
+ // Fl::wait().
+ Fl::add_fd(thread_filedes[0], FL_READ, thread_awake_cb);
+
+ // Set lock/unlock functions for this system, using a system-supplied
+ // recursive mutex if supported...
+# ifdef PTHREAD_MUTEX_RECURSIVE
+ if (!lock_function_init_rec()) {
+ fl_lock_function = lock_function_rec;
+ fl_unlock_function = unlock_function_rec;
+ } else {
+# endif // PTHREAD_MUTEX_RECURSIVE
+ lock_function_init_std();
+ fl_lock_function = lock_function_std;
+ fl_unlock_function = unlock_function_std;
+# ifdef PTHREAD_MUTEX_RECURSIVE
+ }
+# endif // PTHREAD_MUTEX_RECURSIVE
+ }
+
+ fl_lock_function();
+ return 0;
+}
+
+void Fl_Posix_System_Driver::unlock() {
+ fl_unlock_function();
+}
+
+// Mutex code for the awake ring buffer
+static pthread_mutex_t *ring_mutex;
+
+void Fl_Posix_System_Driver::unlock_ring() {
+ pthread_mutex_unlock(ring_mutex);
+}
+
+void Fl_Posix_System_Driver::lock_ring() {
+ if (!ring_mutex) {
+ ring_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
+ pthread_mutex_init(ring_mutex, NULL);
+ }
+ pthread_mutex_lock(ring_mutex);
+}
+
+#else // ! HAVE_PTHREAD
+
+void Fl_Posix_System_Driver::awake(void*) {}
+int Fl_Posix_System_Driver::lock() { return 1; }
+void Fl_Posix_System_Driver::unlock() {}
+void* Fl_Posix_System_Driver::thread_message() { return NULL; }
+
+//void lock_ring() {}
+//void unlock_ring() {}
+
+#endif // HAVE_PTHREAD
diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
index 1860bc8b3..a31d5248b 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
+++ b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
@@ -1,7 +1,7 @@
//
// Windows system driver for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2010-2020 by Bill Spitzak and others.
+// Copyright 2010-2021 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -119,6 +119,8 @@ public:
virtual void remove_fd(int);
virtual void gettime(time_t *sec, int *usec);
virtual char* strdup(const char *s) { return ::_strdup(s); }
+ virtual void lock_ring();
+ virtual void unlock_ring();
};
#endif // FL_WINAPI_SYSTEM_DRIVER_H
diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
index 9c9d35553..38fd50a3d 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
@@ -1,7 +1,7 @@
//
// Definition of Windows system driver for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2020 by Bill Spitzak and others.
+// Copyright 1998-2021 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -15,6 +15,7 @@
//
#include <config.h>
+#include <FL/platform.H>
#include "Fl_WinAPI_System_Driver.H"
#include <FL/Fl.H>
#include <FL/fl_utf8.h>
@@ -957,3 +958,67 @@ void Fl_WinAPI_System_Driver::gettime(time_t *sec, int *usec) {
*sec = t.time;
*usec = t.millitm * 1000;
}
+
+//
+// Code for lock support
+//
+
+// These pointers are in Fl_win32.cxx:
+extern void (*fl_lock_function)();
+extern void (*fl_unlock_function)();
+
+// The main thread's ID
+static DWORD main_thread;
+
+// Microsoft's version of a MUTEX...
+static CRITICAL_SECTION cs;
+static CRITICAL_SECTION *cs_ring;
+
+void Fl_WinAPI_System_Driver::unlock_ring() {
+ LeaveCriticalSection(cs_ring);
+}
+
+void Fl_WinAPI_System_Driver::lock_ring() {
+ if (!cs_ring) {
+ cs_ring = (CRITICAL_SECTION*)malloc(sizeof(CRITICAL_SECTION));
+ InitializeCriticalSection(cs_ring);
+ }
+ EnterCriticalSection(cs_ring);
+}
+
+//
+// 'unlock_function()' - Release the lock.
+//
+
+static void unlock_function() {
+ LeaveCriticalSection(&cs);
+}
+
+//
+// 'lock_function()' - Get the lock.
+//
+
+static void lock_function() {
+ EnterCriticalSection(&cs);
+}
+
+int Fl_WinAPI_System_Driver::lock() {
+ if (!main_thread) InitializeCriticalSection(&cs);
+
+ lock_function();
+
+ if (!main_thread) {
+ fl_lock_function = lock_function;
+ fl_unlock_function = unlock_function;
+ main_thread = GetCurrentThreadId();
+ }
+ return 0;
+}
+
+void Fl_WinAPI_System_Driver::unlock() {
+ unlock_function();
+}
+
+void Fl_WinAPI_System_Driver::awake(void* msg) {
+ PostThreadMessage( main_thread, fl_wake_msg, (WPARAM)msg, 0);
+}