summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FL/Fl.H10
-rw-r--r--src/Fl_lock.cxx63
-rw-r--r--src/Fl_win32.cxx5
-rw-r--r--test/threads.cxx13
4 files changed, 91 insertions, 0 deletions
diff --git a/FL/Fl.H b/FL/Fl.H
index 8c07365e6..547a8f35a 100644
--- a/FL/Fl.H
+++ b/FL/Fl.H
@@ -46,6 +46,7 @@ typedef void (Fl_Label_Measure_F)(const Fl_Label*, int&, int&);
typedef void (Fl_Box_Draw_F)(int,int,int,int, Fl_Color);
typedef void (*Fl_Timeout_Handler)(void*);
+typedef void (*Fl_Awake_Handler)(void*);
class FL_EXPORT Fl {
Fl() {}; // no constructor!
@@ -79,6 +80,14 @@ public: // should be private!
static void (*idle)();
static void (*awake_cb)(void *);
+ static Fl_Awake_Handler *awake_ring_;
+ static void **awake_data_;
+ static int awake_ring_size_;
+ static int awake_ring_head_;
+ static int awake_ring_tail_;
+
+ static int add_awake_handler_(Fl_Awake_Handler, void*);
+ static int get_awake_handler_(Fl_Awake_Handler&, void*&);
static const char* scheme_;
static Fl_Image* scheme_bg_;
@@ -267,6 +276,7 @@ public:
static void lock();
static void unlock();
static void awake(void* message = 0);
+ static int awake(Fl_Awake_Handler cb, void* message = 0);
static void set_awake_cb(void (*cb)(void *)) { awake_cb = cb; }
static void* thread_message();
diff --git a/src/Fl_lock.cxx b/src/Fl_lock.cxx
index 31206c8e7..7541a0cae 100644
--- a/src/Fl_lock.cxx
+++ b/src/Fl_lock.cxx
@@ -29,6 +29,8 @@
#include <FL/Fl.H>
#include <config.h>
+#include <stdlib.h>
+
/*
From Bill:
@@ -68,6 +70,62 @@
void (*Fl::awake_cb)(void *);
+Fl_Awake_Handler *Fl::awake_ring_;
+void **Fl::awake_data_;
+int Fl::awake_ring_size_;
+int Fl::awake_ring_head_;
+int Fl::awake_ring_tail_;
+const int AWAKE_RING_SIZE = 1024;
+
+int Fl::add_awake_handler_(Fl_Awake_Handler func, void *data)
+{
+ int ret = 0;
+ Fl::lock();
+ if (!awake_ring_) {
+ awake_ring_size_ = AWAKE_RING_SIZE;
+ awake_ring_ = (Fl_Awake_Handler*)malloc(awake_ring_size_*sizeof(Fl_Awake_Handler));
+ awake_data_ = (void**)malloc(awake_ring_size_*sizeof(void*));
+ }
+ if (awake_ring_head_==awake_ring_tail_-1 || awake_ring_head_+1==awake_ring_tail_) {
+ // ring is full. Return -1 as ann error indicator.
+ ret = -1;
+ } else {
+ awake_ring_[awake_ring_head_] = func;
+ awake_data_[awake_ring_head_] = data;
+ ++awake_ring_head_;
+ if (awake_ring_head_ == awake_ring_size_)
+ awake_ring_head_ = 0;
+ }
+ Fl::unlock();
+ return ret;
+}
+
+int Fl::get_awake_handler_(Fl_Awake_Handler &func, void *&data)
+{
+ // this function must only be called from within the event
+ // loop which is locked, so don't bother creating any locks
+ if (!awake_ring_)
+ return -1;
+ if (awake_ring_head_ == awake_ring_tail_)
+ return -1;
+ func = awake_ring_[awake_ring_tail_];
+ data = awake_data_[awake_ring_tail_];
+ ++awake_ring_tail_;
+ if (awake_ring_tail_ == awake_ring_size_)
+ awake_ring_tail_ = 0;
+ return 0;
+}
+
+//
+// 'Fl::awake()' - Let the main thread know an update is pending
+// and have it cal a specific function
+//
+int Fl::awake(Fl_Awake_Handler func, void *data) {
+ int ret = add_awake_handler_(func, data);
+ Fl::awake();
+ return ret;
+}
+
////////////////////////////////////////////////////////////////
// Windows threading...
#ifdef WIN32
@@ -203,6 +261,11 @@ void* Fl::thread_message() {
static void thread_awake_cb(int fd, void*) {
read(fd, &thread_message_, sizeof(void*));
if (Fl::awake_cb) (*Fl::awake_cb)(thread_message_);
+ Fl_Awake_Handler *func;
+ void *data;
+ while (Fl::get_awake_handler_(func, data)==0) {
+ (*func)(data);
+ }
}
// These pointers are in Fl_x.cxx:
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index 6fc64c778..4df22baae 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -300,6 +300,11 @@ int fl_wait(double time_to_wait) {
// Used for awaking wait() from another thread
thread_message_ = (void*)fl_msg.wParam;
if (Fl::awake_cb) (*Fl::awake_cb)(thread_message_);
+ Fl_Awake_Handler func;
+ void *data;
+ while (Fl::get_awake_handler_(func, data)==0) {
+ func(data);
+ }
}
TranslateMessage(&fl_msg);
diff --git a/test/threads.cxx b/test/threads.cxx
index fdd2f553c..c7107c235 100644
--- a/test/threads.cxx
+++ b/test/threads.cxx
@@ -32,6 +32,7 @@
# include <FL/Fl_Window.H>
# include <FL/Fl_Browser.H>
# include <FL/Fl_Value_Output.H>
+# include <FL/fl_ask.h>
# include "threads.h"
# include <stdio.h>
# include <math.h>
@@ -42,12 +43,20 @@ Fl_Browser *browser1, *browser2;
Fl_Value_Output *value1, *value2;
int start2 = 3;
+void magic_number_cb(void *p)
+{
+ Fl_Value_Output *w = (Fl_Value_Output*)p;
+ w->labelcolor(FL_RED);
+ w->redraw_label();
+}
+
void* prime_func(void* p)
{
Fl_Browser* browser = (Fl_Browser*) p;
Fl_Value_Output *value;
int n;
int step;
+ char proud = 0;
if (browser == browser2) {
n = start2;
@@ -86,6 +95,10 @@ void* prime_func(void* p)
// message we pass here isn't used for anything, so we could also
// just pass NULL.
Fl::awake(p);
+ if (n>10000 && !proud) {
+ proud = 1;
+ Fl::awake(magic_number_cb, value);
+ }
} else {
// This should not be necessary since "n" and "step" are local variables,
// however it appears that at least MacOS X has some threading issues