5
\$\begingroup\$

Since std::latch is not in many standard C++ libraries, I tried implementing my own, is it OK from memory ordering perspective or yielding?

class Latch {
    std::atomic<unsigned> count;

public:
    explicit Latch(unsigned cnt)
        : count(cnt)
    {
    }

    void arrive_and_wait()
    {
        assert(count > 0);

        count.fetch_sub(1, std::memory_order_release);
        while (count.load(std::memory_order_acquire) > 0) {
            std::this_thread::yield();
        }
    }
};
```
\$\endgroup\$
2
\$\begingroup\$

First the obvious stuff: the real std::latch::arrive_and_wait is specified to take a ptrdiff_t parameter that defaults to 1, but would also support e.g. myLatch.arrive_and_wait(2). Also, there are more member functions than just arrive_and_wait.

I'd call your thing a "spinlatch" (by analogy to "spinlock"), because it doesn't actually put the thread to sleep — it has an operation named arrive_and_wait that doesn't actually do any waiting! It just keeps loading and loading the atomic variable until it sees zero.

To make it actually wait, you could use the also-new-in-C++20 futex facilities of std::atomic, like this:

void arrive_and_wait(int n = 1) {
    int current = (count -= n);
    if (current == 0) {
        count.notify_all();
    } else {
        while (current != 0) {
            count.wait(current);
            current = count.load();
        }
    }
}

No comment on the memory orders.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Assuming author is talking about std version wihout latch, it's not posible to use C++20 futex you suggest. \$\endgroup\$ – Bogdan Mart Jul 12 at 23:18
  • \$\begingroup\$ But perhaps condition variables could be used. They are both present in WinAPI and libc of unix \$\endgroup\$ – Bogdan Mart Jul 12 at 23:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.