summaryrefslogtreecommitdiff
path: root/src/Fl_lock.cxx
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2007-03-06 17:15:03 +0000
committerMatthias Melcher <fltk@matthiasm.com>2007-03-06 17:15:03 +0000
commit11a15d83a2be539c0e660c20ab92d8d4d2736f99 (patch)
tree72283c2251a13b51143774d34d48efc79c67f5fc /src/Fl_lock.cxx
parent6df72e8979a4276f799b4237c0b1f66b695b9b1b (diff)
This is a suggested change. It is complete except for documentation.
I did not like the awake_cb system at all. These changes implement Fl::awake(Fl_Awake_Handler, void*) which is called from a thread and tells the main loop to call the specified handler (rather a callback I guess) as soon as possible from within the main thread. It is implemented as Fifo (currently 1024 entry ring buffer), so handlers are called in the order that they are generated in. "test/threads" was modified to change the label color as soon as a thread reaches 10000 - pretty boring, but it show the wonderful simplicity of this approach: you can write libraries that don't need to add to the main loop or register a handler at all... . I will do some more stress testing tonight. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@5729 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_lock.cxx')
-rw-r--r--src/Fl_lock.cxx63
1 files changed, 63 insertions, 0 deletions
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: