On 1 Dec 2007, at 2:10, Frank Eory wrote:
> In Windows, I used a CreateThread to run a thread processing the
> serial port and changing the value of some text widgets and drawing
> lines. The actual redrawing of the widgets only occur if I move the
> mouse, while the GUI widgets change if I interact with them. If in
> my new thread I use either Fl::flush() or Fl::check(), the widgets
> that I change in the thread get redrawn, but if I click on the
> widgets to slide or change their values they are totally frozen.
A few things to note:
Firstly; 1.1.6 is quite old, there's been a lot of enhancement added,
some of which has enhanced the threading support. I strongly advocate
that you switch to one of the 1.1.8 snapshots and use that.
Secondly: The 1.1.8 docs now include a chapter on threading that
should answer a lot of your questions.
Thirdly: Don't use CreateThread, it has "issues" with how it
interacts with the C runtime. Even the M$ docs suggest that you use
_beginthread instead. Additionally, _beginthread has a signature
quite similar to that of pthread_create, making it easy to wrap them
in a portability layer, to compile your code for either win32 or unix
hosts. See the threads demo in the test folder for a worked example,
(in threads.h - but I can't recall if that's in 1.1.6, I think it is.)
Fourthly: (Is fourthly a word? Sounds odd...) It is not safe to call
flush() or check() from the child thread, only from the main thread.
Use awake() instead. I'm fairly sure this is in the docs, actually.
> Could the fact that I have two concurrent writers somehow
> corrupting the data structures in FLTK?
Yes, calling flush() or check() from the child thread is generally a
Bad Thing. In fact, a lot of windowing systems (and MS Windows is one
of them) can be quite sensitive to how the graphics layer is
accessed. Once you start accessing the graphics system asynchronously
from more than one thread, odd things can start to happen!
> Is there a recommended different way to for me to have an
> additional custom thread?
I do not believe there is one right way - there are many different
ways to address this problem.
> Also, how do I rebuild the fltkd.lib in MS Visual C++?
I don't use the MS tools much anymore - it is not just a matter of
setting the correct build target in the IDE, then rebuilding one of
the test examples?
> This might be the more appropriate question. What is the correct
> way to have a thread to run in parallel with the GUI event handler?
There's no one way that is more correct than any other. Indeed, a lot
of thread-like problems can be solved without threads at all, simply
by judicious use of polling and add_timeout() from a single thread.
However, assuming you do need more than one thread, here's what I'd do:
- The fltk thread runs in the main() thread.
- A lot of windowing systems (win32 being one of them) get "a bit
funny" if you start creating and destroying window widgets (and that
includes pop-ups and alerts) from any thread other than the main
thread. It is possible, but requires tricky workarounds. So, create
all your windows and menus in the main thread. In fact, lets just
make sure all widget creation and deletion is done in the main thread
- that's safest and most portable!
- Your child thread is written as a void function that takes a void
param. void my_task(void); That's usually simplest.
- IPC between the threads? Simplest solution is global variables -
but that might not be the most robust!
- When your program runs, do these steps;
-- In main, before you show() the first window, call Fl::lock();
once, and only once. This activates fltk's thread support (thereafter
fltk will manage locking in the main thread automatically.) You do
need to manage the locks in the child thread yourself, however.
-- show() the first window.
-- When ready, start your child thread using pthread_create/
_beginthread as appropriate.
- Now, when the child thread needs to update a widget's value, do this;
Fl::lock();
my_widget->value(thing);
Fl::unlock();
Fl::awake();
(Note: you can do fancy stuff with the awake() method in 1.1.8 - this
is the simplest case, and the only option in 1.1.6, IIRC.)
- Have the child thread check a global exit flag or something
periodically - and have the main thread set that flag on exit. Or use
some other mechanism to ensure that the child thread terminates
itself when the main thread terminates. Win32 is not all that good at
reaping child threads when the main thread dies, leaving broken bits
of your app running in the background...
That should be enough to get you running,
--
Ian
_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk