[fltk.general] Correct way to fire graphics updates from a background thread

2013-03-18 Thread memoryl...@tin.it
Hi all,
just to have confirmation of what I am doing.
My app is multithreaded ; the main() loop and some other working threads, 
receiving / sending data and doing calculations.

The question: what is the correct way to fire a graphics update from a thread ?

My work (omitted all sanity checks):

- main:
.
static int fd_refresh[2];
.
pipe(fd_refresh);
SetNonblocking(fd_refresh[0]);
SetNonblocking(fd_refresh[1]);
Fl::add_fd(fd_refresh[0], Do_refresh_callback, NULL);
.
#define CMD_REFRESH 0
.
static void Do_refresh_callback(int fd, void *data)
{
 unsigned int val;
 while(read(fd, amp;val, sizeof(val))  0)
 {
  switch(val)
  {
   case CMD_REFRESH:
   // HERE I can draw to screen !
   break;
   .
  }
 }
.
}

- A thread receives data and wants to update a drawing. It cannot do it 
directly,
so it writes to fd_refresh[1] an integer which values represent what I want to 
do
(full redraw(), partial updates, etc.) .
Fltk then will call Do_refresh_callback and there I will be safe drawing 
anything.

Is this sequence correct ?
Now it's working without (apparent) problems.

Thanks,
regards

Lucio

 
___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] Correct way to fire graphics updates from a background thread

2013-03-18 Thread memoryl...@tin.it
Me:
  The question: what is the correct way to fire a graphics update from
 a thread ?

Albrecht:
 Others will probably chime in and tell you more about programming with
 threads and FLTK.

Ian:
 Ah... That quite possibly means me then...
:-)

 Firstly, a caveat: Rendering to the display device from any thread other than 
 the main thread is not robust (may work on some systems, will fail in 
 horrible, hard to debug ways, on others, so do not do that.)
I can confirm this. REALLY horrible ways.

 Instead, all drawing is done from the main thread. In particular, note that 
 creating/deleting/hiding/showing windows *has* to be done by the main 
 thread.
 However, if you create your widgets in the main thread, you can alter them 
 from other threads quite safely, if you use the fltk locking methods. You can 
 signal updates between threads using Fl::awake(); there's no need to get 
 fancy with pipe's  and so forth (fltk is handling that internally) and it is 
 more portable.
Here's a simple recipe for this:

- in the main thread, before you create any windows, call Fl::lock(); *just 
once* to enable thread support. (Do not do any more locking/unlocking in the 
main thread, let fltk manage that for you.)

- in a worker thread, if you want to update a widget, do:

   Fl::lock();
   my_widget-change_this();
   my_other_widget-change_that(value);
   etc.;
   Fl::unlock();
   Fl::awake();

And that should update the widgets in a thread-safe way, then flag the main 
thread to manage the redraw sequence.

In my first app I used Fl::lock, but when the app is growing I have to be 
careful not to create deadlocks, as threads can communicate with each other.
Nothing impossible, but I found the pipe method a little easier to debug.

 Note that Fl::awake can also be passed a callback function - the main 
 thread will then execute that callback in its context, 
 allowing the worker threads to do some operations that would not otherwise be 
 allowed 
 (e.g. you may be able to use this to create new windows under the control of 
 a child thread, since the actual creation will occur in the context of the 
 main thread.)

This is interesting. I missed it.

 However, that is often not necessary, the simple case I outlined above covers 
 a lot of use cases.

Albrecht and Ian, thank you for your help.
If you are coming to Italy let me know, beer ready for you !

Thanks,
regards

Lucio


 
___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] Correct way to fire graphics updates from a background thread

2013-03-18 Thread MacArthur, Ian (Selex ES, UK)

 In my first app I used Fl::lock, but when the app is growing I have to
 be careful not to create deadlocks, as threads can communicate with
 each other.

Sure; but the Fl::lock() is a mutex, so you must only take it immediately 
before you want to modify the widgets, and you release it as soon as possible.

You never hold the lock for any longer than is necessary, and you do nothing 
but fltk GUI operations within the lock, so there should be no scope for 
deadlocking.

That said, if you need to be handling incoming data asynchronously (and at a 
high rate) you want to be separating that out from the GUI update process 
anyway - see Edzard's note on queuing up data for processing, then dealing with 
that at user rates, not at input rates.




Selex ES Ltd
Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS14 
3EL
A company registered in England  Wales.  Company no. 02426132

This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.


___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] Correct way to fire graphics updates from a background thread

2013-03-18 Thread memoryl...@tin.it
Sure; but the Fl::lock() is a mutex, so you must only take it immediately 
before you want to modify the widgets, and you release it as soon as possible.
You never hold the lock for any longer than is necessary, and you do nothing 
but fltk GUI operations within the lock, so there should be no scope for 
deadlocking.
That said, if you need to be handling incoming data asynchronously (and at a 
high rate) you want to be separating that out from the GUI update process 
anyway - 
see Edzard's note on queuing up data for processing, then dealing with that at 
user rates, not at input rates.

Nice ideas ; actually the separation is done from the pipe, which buffers 
update requests.
Explicitly buffering is much more elegant. Thanks.

regards
Lucio


 
___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk