[SDL] how to detect if a thread is still running

Huib-Jan Imbens hj at imbens.nl
Wed Jul 24 01:59:00 PDT 2002


> There are very few reasons to create another thread for something, and
> more often I see thread abuse than use. It might be tempting (whizzy/cool)
> to use a thread, but there are so few circumstances when it's actually
> needed that when someone says they need a thread for something, more often
> than not they don't!

May be I should have explained the situation in which I intended to use
SDL_ThreadIsRunning () a bit more.
The code below shows the relevant parts of my event loop (which is run in
the main thread).

 ready = SDL_FALSE;
 while (!ready) {
  // redraw all areas that have been invalidated
  if (gView) gView->Update ();

  // perform all tasks
  SFTaskManager::GlobalTaskManager ().DoTasks ();

  // handle network events
  SFTCPClientManager::GlobalTCPClientManager ().DoTCPClients ();

  // poll events and handle them
  SDL_Event event;
  while ( SDL_PollEvent(&event) ) {
   switch (event.type) {
    case SDL_QUIT: /* Quit now */
     ready = SDL_TRUE;
     break;
    case SDL_KEYUP:
     SFKeyboardHandlerManager::GlobalKeyboardHandlerManager ().HandleKeyUp
(event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode);
     break;
    case SDL_MOUSEBUTTONUP:
     if (gView) {
      gView->HandleMouseMove (*gView, event.button.x, event.button.y);
      gView->HandleMouseUp (*gView, event.button.button);
     }
     break;
    case .....:
     break;
   }
  }
 }

The thread that I want to know the status of, is started somewhere deep in
the HandleMouseUp call and is calculating a chess move. That takes some
time. In the mean time I want the GUI to stay responsive. Eg. one of the
tasks registered to the GlobalTaskManager updates a chess clock on the
screen and I don't want that clock to pause while the move is being
calculated. In another one of the tasks registered to the GlobalTaskManager
I want to check whether the chess thread has finished so I can perform the
move.

Latency is not an issue at all. Besides I don't see a reason why latency
would be large unless the GUI is very busy.

Of course there are ways to do this without a thread. I could split up the
move calculation in small pieces and call those pieces from a task. I could
also make a copy of my event loop and call that copy every now and then from
the chess code. In both cases the chess code would be a lot more complicated
and dependent on this particular GUI.

> int StartCalculateThread(void *)
> {
>   uint i;
>   for(i=0; i<1000000; i++)
>   {
>     /* Calculate Stuff */
>   }
>   /* I'm about to exit: tell the world! */
>   IsCalculateThreadAboutToExit = true;
> }
>
> void LaunchCalculateThread()
> {
>   IsCalculateThreadAboutToExit = false;
>   SDL_CreateThread(StartCalculateThread);
> }
>
> bool IsThreadStillRunning()
> {
>   return (!IsCalculateThreadAboutToExit);
> }

Ok, let us assume some imaginary OS and hardware where:
1. a bool is stored as 4 bytes.
2. true is stored as 0xffffffff, false is stored as 0x00000000
3. !IsCalculateThreadAboutToExit is compiled as IsCalculateThreadAboutToExit
== 0
3. hardware stores 2 bytes at a time (may be only in special cases where the
4 bytes are in two different pages)

Now with a dying thread I risk that I get a context switch after the first
half of IsCalculateThreadAboutToExit has been set. So inthe main thread
IsThreadStillRunning () will return true.
So in some imaginary app, I might immediately, that is in the same timeslice
start a new thread. After another context switch the dying thread would be
setting the other half of IsCalculateThreadAboutToExit and I would assume
that the other thread would have finished as well.

May be this guaranteed to never happen but I prefer not to think about these
issues and rely on an API call that someone smarter than me has written and
that many smart people have reviewed.

> Also, don't forget to declare it volatile. ;-)

That is a good point, but probably not very important in my case because I
would check it only once each event loop deep down in
SFTaskManager::GlobalTaskManager ().DoTasks ();, so I am confident that my
compiler will not be able to optimize the check away.
However the very fact that you have to think about such subtleties made me
ask whether I overlooked some SDL API call.

Huib-Jan







More information about the SDL mailing list