[haiku-3rdparty-dev] Re: Thread Control

  • From: Ingo Weinhold <ingo_weinhold@xxxxxx>
  • To: haiku-3rdparty-dev@xxxxxxxxxxxxx
  • Date: Tue, 26 Jun 2012 17:10:47 +0200

On 2012-06-26 at 14:47:11 [+0200], Philippe Houdoin 
<philippe.houdoin@xxxxxxxxx> wrote:
>  If you consider that fetching RSS will take way less time than the
> sleep period as it seems, a better way will to spawn *each* hour a
> fire & forget thread that only does the fetch and die.
> While a thread can perfectly stay asleep for a long time, there is no
> point if it's only to wait the next hour : your main thread can
> perfectly do that too. What needs actually to run in parallel is the
> task itself, nothing more, nothing less.
> 
> If your application has a BApplication objet, you can use a
> BMessageRunner to send itself a "fetch now" message at periodic
> interval. On reception of this message (in your
> BApplication::MessageReceived() method), you spawn and resume a fetch
> thread, which will die itself when his task is done.

+1

> > Do I need to stop the thread myself when
> > the application quits?
> 
> Yes. An application (a "team" in Haiku terminology) only ends when his
> last thread ends.

That is not correct. A team terminates when exit() is called or the main 
thread dies. You do want to orderly terminate your program, though, so that 
threads aren't in the middle of writing something to disk or something like 
that. The BeAPI already does that for windows when the application is asked 
to quit. For threads you create yourself, you need to do that yourself. 
Usually you would overwrite QuitRequested() of your BApplication or a 
BWindow (whatever the thread is associated with) and quit your thread there 
or do that in the destructor (depends on how thread interacts with the 
BApplication/BWindow).

> > What would be the best way to stop the thread?
> 
> It totally depends on what can wakeup it.
> 
> If it spents most of his time blocked in a system call, like snooze()
> in your current design, what you needs it to wakeup from it and check
> if the wakeup is due to exit condition.
> 
> You can do that mostly by two ways:
> 1) interrupt the syscall, by sending a signal to your thread. Then
> checking the error is B_INTERRUPTED and that some boolean variable
> StopTask was meanwhile set to true...

This is a relatively unusual method on BeOS and Haiku. There's also a race 
condition. E.g. if your thread does (pseudo code):

  while (true) {
    do work;

    if (shallTerminate)
       return;
    snooze(waitTime);
  }

and the signal arrives right after the shallTerminate check, but before the 
snooze(), the thread would still wait and only return in the next iteration.

> 2) from another/main thread, close/free/delete the system resource
> used by the system call made in your task thread. The call will
> returns an error saying that the resource is not more
> available/valid/opened, which is your signal to exit.

A typical way to do that here would be to replace the snooze() by a 
acquire_sem_etc() on a semaphore with a timeout of how long it shall wait. 
The semaphore would have to be created with count 0, so that the thread 
actually blocks and only unblocks after the timeout. When the thread shall 
be terminated, you can just delete the semaphore and the thread will wake up 
immediately, if it is waiting. You'll have to check the return value of 
acquire_sem_etc() to see which one happened. A third return value is 
B_INTERRUPTED which can happen when signals are delivered. Just continue the 
to wait in this case -- use an absolute timeout, so you don't increase the 
wait time.

Another method of orderly termination of the thread is pthread_cancel(). It 
was introduced post alpha 3, so, depending on which Haiku version you 
develop, it may not yet be available.

Anyway, as Philippe already wrote, the it probably the best option to start 
your worker thread on demand. You might still consider a method to terminate 
it quickly while it is doing its work. Since it uses networking 
functionality, it can take a very long time in case of network issues and 
you don't want your application to hang when it is asked to quit. E.g. in 
case of blocking socket reads/writes use nonblocking ones and poll() or even 
better wait_for_objects() with an additional semaphore that can be used to 
notify the thread to quit.

CU, Ingo

Other related posts: