Re: Multithreading stuff
- From: Chris Vine <chris cvine freeserve co uk>
- To: michi7x7 <mailing-lists michi7x7 de>
- Cc: gtkmm-list gnome org
- Subject: Re: Multithreading stuff
- Date: Sun, 27 Jun 2010 11:09:29 +0100
On Sun, 27 Jun 2010 09:17:19 +0200
michi7x7 <mailing-lists michi7x7 de> wrote:
> Chris Vine wrote:
> > This won't work. The default constructor of a dispatcher will
> > cause its callbacks to execute in the main program thread (it can
> > be constructed to execute in another thread if that other thread
> > has its own main loop, but your worker thread doesn't have one).
> > Apart from that, connecting to a dispatcher object is only thread
> > safe if the connection is made in the same thread as that in which
> > the callback will execute, which you don't do, and it must also be
> > constructed in that thread.
> > I am also not sure that a dispatcher can be created as a global
> > object because at the time of creating it, g_thread_init() will not
> > have been called (I am not sure about that one).
> > The trite answer to the OP's problem is that if the OP doesn't know
> > how to do something as simple as this, he probably shouldn't be
> > programming with threads because he stands to get quite a few other
> > things wrong. The more helpful answer is that given the awful
> > design (looping with usleep() in the worker thread), he can have a
> > flag which is set by the main program thread and which is read on
> > each iteration by the worker thread which tells the worker thread
> > to exit by throwing Glib::Thread::Exit.
> > To be standard conforming, the flag ought to be protected by a mutex
> > or be a glib atomic type (I don't think atomic operations are
> > wrapped in glibmm but if not the glib C interface can be used).
> > Chris
> So it's only possible if he had a seperate Glib::MainLoop within this
> new Thread?
> And instead of using usleep he should use SignalTimeout, am i right?
> So Michael, you could use either SignalTimeout on the MainLoop run by
> the Main-Program, or create a new MainLoop which then runs within
> another thread.
> -> MainLoop
> -> MainLoop
> --> SignalTimeout
> But you can't use a Dispatcher to kill this second thread here
> either, because it will only get called, if the MainLoop continues
> running. There is no way to kill threads in Glibmm, so you should
> simply avoid calling blocking functions.
> http://www.mail-archive.com/gtkmm-list gnome org/msg03468.html
You can use Glib::Dispatcher to cause the worker thread to execute a
callback if it has its own main loop. However, you cannot throw
Glib::Thread::Exit in such a callback as the glib main loop has C
linkage specification and cannot propagate C++ exceptions. You could
call g_thread_exit(), but if that is done destructors of any objects on
the stack will not be called with windows nor with linux/BSD
distributions using linuxthreads as opposed to NPTL. That is not a
problem if all objects with destructors are constructed in free store
and clean up is done manually using delete/delete before
g_thread_exit() is called.
Contrary to what the message you reference says, it is safe for the
main thread to call pthread_cancel() on the worker thread directly if
using NPTL (which all recent, say last 4 years, linux/BSD distributions
use) in a Unix-like environment. NPTL will cause the stack to unwind
with a pseudo-exception. It is safe to call pthread_cancel() even in
linuxthreads if there are no local objects with destructors on the
stack (that is, they are all constructed on free store) and all clean-up
is done with pthread_cleanup_push() and pthread_cleanup_pop() with
handlers which call delete/delete by hand. For that purpose, you
can (and should) choose the cancellation point with
pthread_setcancelstate() so that cancellation only actually occurs when
a suitable point in the code is reached. This won't help if the OP is
using windows of course.
If these pre-conditions are met, calling pthread_cancel() is in my view
the optimal solution. Another way of achieving something similar is to
call pthread_kill() which will send a signal to the worker thread. The
signal handler can set a flag for the worker thread to inspect
periodically. The signal will also interrupt any blocking system calls
in the worker thread with a EINTR error provided that the SA_RESTART
flag has not been set with sigaction(), and the worker thread can then
arrange to terminate itself by throwing Glib::Thread::Exit if it does
not have its own glib main loop, or calling g_thread_exit() if it has
(as to which see my first paragraph above).
] [Thread Prev