Thread Synchronization Issue ( Win32 )

Started by
3 comments, last by GameDev.net 18 years, 4 months ago
Heya all, I having some problems with my threading system. I use critical sections to safeguard my data. The problem is when shutting down. I have a couple of tasks running. These tasks inform the 'task manager' when they have completed. The task manager itself is also safeguarded with a CS. Somehow it isn't syncing, although I have locking and unlocking mechanisms they seems to miss each other completely. It takes five minutes for them to 'sync' and shut the program down. I am sure it is not processing the task, instead it is trying to notify the tsk manager that it is complete. ( see NotifyComplete() in pseudo code ) What can I do about this problem? I tried Sleep() timers, still it's a luck of the draw when they 'sync'. The taskmanager will not shutdown ( holds up main thread ) till all tasks are complete. Below is some pseudo C++ code as to how my task system works.

void NotifyComplete( uint32 task )
{
  LockWaitCS();
  // set task as complete
  UnlockCS();
}

void TaskProc( void *task_info )
{
  while ( Thread_Run())
  {
    LockWaitCS();
    // process task
    NotifyComplete( task_id );
    UnlockCS();
  }
}

void TaskManagerShutdown( void )
{
  LockWaitCS();

  while ( tasks_running )
  {
    // allow the task to notify us when it is complete
    // by releasing access to the CS so NotifyComplete
    // can mark the task as complete
    UnlockCS();
    Sleep(1);

    // gain access once more so we can check if all tasks are complete
    LockWaitCS();
    
  }

  UnlockCS();
}



Thanks
Advertisement
The main problem I see here, when using the same lock for your tasks and your task manager is that your tasks can only run, when the Task manager is not using a lock and vice versa...

normally you should guard only Code with critical code, when there can happen a conflict, so that you have for example one guard for shared memory access and one guard for access to a special file...

And for that i would use a classical counting semaphore for your taskmanager:

say you have n tasks:

when all each task starts he makes:

waitForTaskSema( 1 ); // and gets one semaphore from the counting semaphore
// do your job...
releaseTaskSeme( 1 );

Your Taskmanager would just do
WaitForTaskSema( n ); // only when all tasks are finished he can pass this


I think you get the idea...

If you want to learn more about semaphores, there is always the classical Kicking Horse Pass"-Problem
Heya Sparhawk,

I implemented the semaphore and it works perfectly now...except for one problem.

I used to use the critical sections to 'pause' the worker threads. I would keep them 'locked' until they had work then 'unlock' them. It seems if I do the same with the semaphore it still continues to process.

What is a good way to 'pause' a thread till it has work to do?

Thanks!
For one way you could always create new threads and release the old ones...

An other ways depend on the way you schedule tasks...

for one you could give each thread a work semaphore, which will be set you schedule a task for it, and the thread will wait on those one...

or a bit more complicated...

You use taskqueue with also a semaphore which directly refers to the tasks in queue, on those semaphore your threads wait first, and then you need a second semaphore to protect the queue will reading and writing...but this would just be a classical critical section ;-)
The best way to send wakeup signals between threads is to use Event objects, because they're made for exactly that purpose. Make one event per worker thread, then have the worker thread wait on the event object, then to wake it up set the event. If you want to just periodically say 'ok process some stuff now', you would specify FALSE for the ManualReset parameter to CreateEvent so that only a single wait is ended. If you want worker threads to run until the manager stops them, specify TRUE for the ManualReset parameter and set the event to start a thread and reset the event to pause the thread.

Alternately, you could use SuspendThread to arbitrarily halt a thread at any point and ResumeThread to reactivate it, but you have to be very careful with these functions because they can easily cause problems that are very difficult to debug, such as deadlock.

-Extrarius

This topic is closed to new replies.

Advertisement