views:

383

answers:

2

I want to halt one thread till another thread has finished initializing without using pthread_join. I tried using a join but it leads to a deadlock due to some asynchronous inter-thread communication system that we have. Right now, I'm using a (custom) lock to achieve this.

In Thread 1:

lock_OfflineWorker.Lock()
if (pthread_create(&tid0, NULL, RunOfflineWorker, NULL) != 0)
{
}

lock_OfflineWorker.TryLock();
lock_OfflineWorker.Unlock();

In Thread 2:

bool OfflineWorker::Initialize()
{
  lock_OfflineWorker.Unlock();
}

But this is inelegant and I'm not too sure about the side effects (possibility for another deadlock). Is this Ok? If not, is there another way to achieve this (using locks or otherwise)

EDIT: Forgot include the "RunOfflineWorker" function

void* RunOfflineWorker(void* pData)
{   
  g_OfflineWorker.Initialize();
}
+6  A: 

You can use a pthread condition to wait until the job reaches the wanted state.

The thread1 waits with pthread_cond_wait() and the thread2 signals it with pthread_cond_signal().

You need :

bool            condition ; // or anything else to be tested
pthread_mutex_t mutex ;
pthread_cond_t  cond ;

The first thread inits all :

condition = false ;
pthread_mutex_init( &mutex , PTHREAD_MUTEX_INITIALIZER );
pthread_cond_init( &cond , PTHREAD_COND_INITIALIZER );

Then it waits with the mutex locked. Usually you put the wait in a loop to check the condition whatever it is.

pthread_mutex_lock( &mutex );
while( ! condition )
{
    pthread_cond_wait( &cond , &mutex );
}
pthread_mutex_unlock( &mutex );

The other thread does this when appropriate :

pthread_mutex_lock( &mutex );
condition = true ; // or false ...
pthread_cond_signal( &cond );
pthread_mutex_unlock( &mutex );
fa.
Except you forgot to include code needed for the mutex
jpalecek
I got the system to work using a pthread condition. I didn't use a while loop, just called wait on the condition.Should I lock the mutex before calling pthread_cond_wait?Doesn't pthread_cond_wait lock and unlock the given mutex automatically?
Gayan
ok, I added the init.The loop is there to check that the condition is really met, as thread 2 may also use : condition = false ; pthread_cond_signal( cond );Yes you must lock it before, as pthread_cond_wait unlocks it.
fa.
The mutex must be locked to use the condition variable. If you just want to wait until the thread is initialised, then (1) the mutex should be locked just before `condition = true` and unlocked just after, and (2) locked just before `while (!condition)` and unlocked after the loop.
Doug
It works fine now. ThanksWaiting for OL thread // Thread 1Thread registered // Thread 2Taking OL lock // Thread 2...Server created : ...Releasing OL lock // Thread 2Thread created [OfflineWorker] // Thread 1
Gayan
+1  A: 

I think your solution is just fine, except that you need to use lock_OfflineWorker.Lock() instead of lock_OfflineWorker.TryLock() in thread 1 - with TryLock(), it actually doesn't wait for anything. You cannot use a mutex for that, because it needs to be released by the same thread that locked it, but eg. a semaphore based lock would do. Using a monitor (ie. mutex+condvar) would be just more complex.

About deadlocks: Deadlocks are impossible if the initialization part of OfflineWorker (ie. the code before it releases the lock) doesn't wait anywhere. If there are actual deadlocks with your solution, any other solution that makes thread 1 wait for thread 2 would have them too (I can imagine such situation).

Edit after comment: If you pass messages to thread 1 while it is waiting for the initialization of thread 2 to complete, you have a possibility of deadlock, particularly if there is some bounded buffer for messages or if the message passing function waits for reply. In this situation, I would suggest just abandoning the idea of waiting for thread 2 and maybe pass some callback that would be called from thread 2 when initialization finishes.

jpalecek
I've abbreviated the code a lot here. There are functions which pass messages to thread 1 in there but as you said these shouldn't cause any deadlocks. I'll look into that. Thank you
Gayan
@Gayan: See the edit
jpalecek