3

My daemon initializes itself in four different threads before it starts doing its things. Right now I use a counter which is incremented when a thread is started and decremented when it is finished. When the counter hits 0 I call the initialization finished callback.

Is this the preferred way to do it, or are there better ways? I'm using POSIX threads (pthread) and I just run a while cycle to wait for the counter to hit 0.

Edit: pthread_barrier_* functions are not available on my platform although they do seem to be the best choice.

Edit 2: Not all threads exit. Some initialize and then listen to events. Basically the thread needs to say, "I'm done initializing".

Kristina
  • 15,859
  • 29
  • 111
  • 181

6 Answers6

7

A barrier is what you need. They were created for that, when you need to "meet up" at certain points before continuing. See pthread_barrier_*

Julio Guerra
  • 5,523
  • 9
  • 51
  • 75
  • +1 for recommending the right tool for the job, barriers. All of the other solutions are sub-optimal. – R.. GitHub STOP HELPING ICE May 26 '11 at 14:08
  • Continuing is the word here. Only thing is, the other 4 threads won't be continuing afterwards. Barriers are great, but using them here will probably just confound subsequent readers of the code. In short: barriers are overkill when waiting for other threads to terminate. – Klas Lindbäck May 27 '11 at 08:51
  • `pthread_barrier` seems to be perfect, but it isn't available. – Kristina May 27 '11 at 21:43
  • In that case, that would not be difficult to implement it yourself. You almost did it. Simply make your counter thread safe with a lock. – Julio Guerra May 27 '11 at 22:53
  • But this is weird. Maybe they removed it. Some online documentation do talk about barriers in the pthread library. – Julio Guerra May 27 '11 at 22:56
3

pthread_join is the preferred way to wait for pthreads.

Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82
  • 2
    It's the right way to wait for *a particular thread*, but not the right way to wait for "N threads". – R.. GitHub STOP HELPING ICE May 26 '11 at 14:27
  • He just have to wait for each of the four threads in turn. If the other threads were to continue afterwords, barrier would be the choice. To me it seems unintuitive for all threads to wait for each other and then all but one just terminate. – Klas Lindbäck May 27 '11 at 08:43
3

That sounds ... weird. Shouldn't you just be using pthread_join() to wait for the threads to complete? Maybe I don't understand the question.

unwind
  • 391,730
  • 64
  • 469
  • 606
3

Rather than spinning, use the pthread mutex/condvar primitives. I'd suggest a single mutex to protect both the count of threads outstanding, and the condvar.

The main loop looks like this:

acquire mutex
count=N_THREADS;
start your N threads
while (1) {
  if (count==0) break;
  cond_wait(condvar);
}
release mutex

And when each thread is ready it would do something like this:

acquire mutex
count--
cond_signal(condvar)
release mutex

(EDIT: I have assumed that the threads are to keep going once they have done their initialisation stuff. If they are to finish, use pthread_join as others have said.)

crazyscot
  • 11,819
  • 2
  • 39
  • 40
0

As Klas Lindbäck pointed out in his answer, joining threads is a preferred way to go. In case your threads are not exiting (i.e. are part of the reusable pool etc.), the logic sounds good. The only thing is that using counter without any synchronisation is dangerous. You have to use either mutex with condition or atomic integer. I'd recommend using mutex + condition if you don't want to spin on atomic counter in the thread that waits for initialisation to finish.

0

So, what happens if one thread finishes initialization before any of the others begin?

So one way to do it

  1. initialize an atomic counter to 0
  2. when each thread is done with init, increment counter and retrieve the value atomically. If you use GCC, you can use __sync_add_and_fetch()
  3. If the retrieved counter value < N_threads, block on a pthread condition variable.
  4. If the retrieved counter value == N_threads, init phase is done, signal the condition and continue.
janneb
  • 36,249
  • 2
  • 81
  • 97