1
std::mutex mutex;
std::condition_variable cv;
uint8_t size = 2;
uint8_t count = size;
uint8_t direction = -1;

const auto sync = [&size, &count, &mutex, &cv, &direction]()  //.
{
    {
        std::unique_lock<std::mutex> lock(mutex);
        auto current_direction = direction;
        if (--count == 0)
        {
            count = size;
            direction *= -1;
            cv.notify_all();
        }
        else
        {
            cv.wait(lock,
                    [&direction, &current_direction]()  //.
                    { return direction != current_direction; });
        }
    }
};

as provided in the first unaccepted answer of reusable barrier

a 'generation' must be stored inside a barrier object to prevent a next generation from manipulating the wake up 'condition' of the current generation for a given set of threads. What I do not like about the first unaccepted answer is the growing counter of generations, I believe that we need only to differentiate between two generations at most that is if a thread satisfied the wait condition and started another barrier synchronization call as the second unaccepted solution suggests, the second solution however was somewhat complex and I believe that the above snippet would even be enough (currently implemented locally inside the main but could be abstracted into a struct). Am I correct in my 'belief' that a barrier can only be used simultaneously for 2 generations at most?

mkmostafa
  • 3,071
  • 2
  • 18
  • 47
  • 1
    Bad things will happen indeed if `count` is 0 at the point of capture. – Bathsheba Sep 26 '17 at 11:32
  • can you elaborate more? count is currently only exposed because I use a lambda, I would change all of that into a struct that takes size as an input with a member function without any parameters – mkmostafa Sep 26 '17 at 11:36
  • I'm not sure I understand the goal here. Off the top, the following is possible. Thread 1 waits for direction to flip. Thread 2 flips direction and notifies all. But before thread 1 has a chance to wake up and check the condition, other threads call `sync` enough times to flip the direction again. Thread 1 would then find the condition to be false, assume a spurious wake, and go back to sleep. It would eventually wake up when the direction flips yet again, for the third (or perhaps fifth, or `N`th for arbitrarily large odd `N`) time. – Igor Tandetnik Sep 30 '17 at 16:50
  • But sync cannot be called enough to cause another flip without thread 1 participating. All participating threads must call sync. The latest thread always flips so in your example, all threads call sync except,m thread 1 (the delayed one) which would eventually call sync after it wakes up and does the flip – mkmostafa Oct 03 '17 at 20:32

0 Answers0