One thread waiting for multiple thread events

Viewed 590

I have one thread waiting for some event from various number of other thread, which depend on an event from this one thread to continue processing. How can I code to avoid busy looping?

More specifically, I have multiple threads that process their respective video frame and write it to a screen buffer (at different locations). After they are all finished, the one thread sends the buffer to draw then those threads wait for the draw call to finish and then proceed to their next frames.

This needs to be implemented in C++. C++ standard used is not limited.

EDIT: std::condition_variable doesn't seem to be the solution. Since it requires a mutex, and the number of threads (mutexes) is known at runtime, and I can't put mutexes in std::vector

The pseudocode of my program is like this:

drawThread:
    loop:
        for each processThread:
            wait for event
        draw()

processThread:
    loop:
        process()
        notify drawThread
        wait for draw to finish

EDIT: What I tried:

std::vector<std::atomic_bool> ready_flags;
std::atomic_bool finished_drawing = false;
void drawThread()
{
    while(true)
    { 
        CHECK:
        for(auto& flag: ready_flags)
        {
            if(!flag)
                goto CHECK;
        }
        draw();
        finished_drawing = true;
    }
}
void ProcessThread(int id)
{
    while(true)
    {
        process();
        finished_drawing=false;
        ready_flags[id] = true;
        while(!finished_drawing)
            ;
    }
}
1 Answers

I sort of figuring out a working solution

const int processThreadCount;
std::atomic<int> ready_count{};
std::shared_mutex drawing_mutex;
std::conditional_variable_any can_draw;
void drawThread()
{
    while(true)
    { 
        std::unique_lock lk{drawing_mutex};
        canDraw.wait(lk, [&]{return ready_count==processThreadCount;};
        draw();
        ready_count=0;
    }
}
void ProcessThread(int id)
{
    while(true)
    {
        std::shared_lock lk{drawing_mutex};
        process();
        ++ready_count;
        can_draw.notify_one();
    }
}
Related