On 12.08.2012, at 23:43, Amadeus W.M. <amadeu...@verizon.net> wrote:

> I'm trying to create my first threaded application with fltk. I have two 
> threads: one that produces stuff and the gui thread. For simplicity, the 
> producer thread just generates random rectangles and tells the gui thread 
> to draw them via Fl::awake(). See code below. 
> 
> The problem is I have to put the producer thread to sleep() for a few 
> seconds right at the beginning of the thread function, to allow for 
> everything else to get going. See makeRectangles() below.
> 
> I imagine this is not the proper way to make sure all threads have 
> started, so what's the right way? 
> 
> Also, the threads.cxx example from fltk-1.1 locks/unlocks in the 
> "producer" thread, but that's because it adds rows to the browsers. I'm 
> not accessing any fltk widgets, so I don't have to lock, is that correct? 
> 
> Finally, there seems to be another way of drawing from a non-gui thread 
> in the gui thread, using Fl::add_fd(), as explained here: 
> 
> http://www.angelfire.com/linux/tzptech/fltk/fltk-mt.pdf
> 
> Is this what Fl::awake() does behind the scenes? 

FLTK is aware of threads and offers sufficient support. There are a few things 
that you can't do in threads, not because FLTK does not want to, but because 
the OS or libraries that FLTK uses, don;t allow that.

You can't create or delete windows in a thread and you can't call Fl::wait(), 
Fl:flush(), or Fl::run(). This implies that you can not call Fl::message() and 
friends.

But in your example, you are running into an entirely different limitation. If 
you want to draw things - not only in threads - it should be done within a 
virtual widget draw() function, derived from another widget. This is important, 
because the OS tells FLTK when it is a good time to draw. FLTK will then set 
the environment so that drawings will be sent to the correct window with the 
correct coordinates, color, patterns, etc. .

There are two ways around this limitation. I have not tested them in threads, 
but they doe work in non-threaded apps. There is a good chance that they will 
work here, too:

1: use an offscreen buffer. Create an offscreen buffer using 
f;_create_offscreen(). Then, whenever your thread wants to draw something, use 
lock(), fl_begin_offscreen(), draw, the fl_end_offscreen(), and unlock(). Then 
have the main thread copy the offscreen buffer into the main window during a 
draw().

2: use Fl_Window::make_current(). As above, use lock(), make_current(), draw, 
unlock()

Please not the begin_offscreen and make_current are relatively expensive calls. 
Using those to draw a single rectangle is probably not very efficient.


The recommended way to write you app would be to use the thread to calculate 
the rectangles, and use a derived class with its own draw() function to draw 
the rectangles from within the main thread. That implies that you need to store 
the location and color of rectangles in a way that both threads an access them 
without conflict.

 - Matthias
_______________________________________________
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to