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