SDL Digest, Vol 18, Issue 7

Alright; fair enough. Here’s the source code for it:

#define NumCPU 4

SDL_cond *Cond;
SDL_mutex *Mutex;
SDL_Thread *Threads[NumCPU] = {0};

int FilterImage(void *ID)
{
do {
// Synchronize threads on start
SDL_CondWait(Cond, Mutex);

    // Do some work
} while (1);

return -1;

}

int main(int ArgC, char *Args[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return -2;

if ((Mutex = SDL_CreateMutex()) == NULL)
    goto Exit;

if ((Cond = SDL_CreateCond()) == NULL)
    goto Exit;

for (int i = 0; i < NumCPU; i++)
    Threads[i] = SDL_CreateThread(&FilterImage, (void *)i);

SDL_Delay(1000);
SDL_CondBroadcast(Cond);

do {
    // Do some work
} while (1);

}

Basically, creating the mutex and the condition variable along with the
threads. Once everything is created, multiple broadcasts are called for
the threads to do work. I am making sure that the threads are created
fully before broadcasting by adding a temporary artificial delay of 1-2s
before the broadcast.> Chris T wrote:

The way I implemented my system, each threads run in a do {} while
(1) loop and the work they want to do is waiting with SDL_CondWait,
triggered by SDL_CondBroadcast from the parent thread which busy loops.
What I notice is that when I fire a broadcast, the first thread runs and
only after it is completed does the second thread go and etc.

That would be the expected behavior if each thread is keeping the mutex
associated with the condition locked for the whole duration of its work.
Are you sure you’re not doing that?

Or am I doing something dumb here?

We can’t tell since you’re not showing us what you’re doing. Seeing your
source code would help diagnose the problem.

-Christian

Chris T wrote:

Alright; fair enough. Here’s the source code for it:

#define NumCPU 4

SDL_cond *Cond;
SDL_mutex *Mutex;
SDL_Thread *Threads[NumCPU] = {0};

int FilterImage(void *ID)
{
do {
// Synchronize threads on start
SDL_CondWait(Cond, Mutex);

   // Do some work

} while (1);

return -1;
}

int main(int ArgC, char *Args[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return -2;

if ((Mutex = SDL_CreateMutex()) == NULL)
goto Exit;

if ((Cond = SDL_CreateCond()) == NULL)
goto Exit;

for (int i = 0; i < NumCPU; i++)
Threads[i] = SDL_CreateThread(&FilterImage, (void *)i);

SDL_Delay(1000);
SDL_CondBroadcast(Cond);

do {
// Do some work
} while (1);
}

OK, what happens here is exactly what I described: you’re serializing
your worker threads using the mutex. Also, note that you should lock the
mutex before calling SDL_CondWait (I don’t know what happens when you
don’t). It will unlock it before going to sleep, and re-lock it before
returning. Your thread function should look something like this:

int FilterImage(void *ID)
{
do {
SDL_LockMutex(Mutex);

    // Check whether there is any work for me (at a shared source
    // that needs to be protected by the mutex)
    while (there is no work for me to do) {
        SDL_CondWait(Cond, Mutex);
    }

    // Fetch some work from the shared source

    SDL_UnlockMutex(Mutex);

    // Do the work (other threads can run concurrently now)
} while (1);

return -1;

}

The while loop around the SDL_CondWait() is important too: by the time
you’re getting the mutex after being awakened by a condition broadcast,
other waiting threads that got to run before you may already have used
up all pending jobs, and you can go to sleep again.

I am making sure that the threads are created
fully before broadcasting by adding a temporary artificial delay of 1-2s
before the broadcast.

I hope you’re aware that you’re not making sure of anything by this? All
you’re doing is increasing the likelihood that the threads will be ready
(to probably close enough to 100% that it doesn’t matter in practice,
but still). Plus, you slow down your application launch needlessly. To
do this properly, you need to have the worker threads notify the main
thread when they’re ready, using another condition, or a semaphore.

Have you considered whether a semaphore might be a better solution for
what you’re trying to achieve than a condition? Unlike the latter, it
doesn’t “lose” the notifications that happen while no one is waiting on
it. And generally, I find that semaphores are easier to get your head
around than conditions. :slight_smile:

Hope this helps somewhat. Thread synchronization is complicated to do
properly, it took me a while to come to grips with it too, and I’m still
not sure I get it completely right (so corrections are welcome if
anything I wrote above is incorrect).

-Christian