C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Standard library should have a simple 'gate' for multithreading

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Fri, 22 Jul 2022 10:49:06 +0100
On Fri, Jul 22, 2022 at 3:36 AM Thiago Macieira via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> On Thursday, 21 July 2022 16:38:16 PDT Frederick Virchanza Gotham via Std-
> Proposals wrote:
> > The reusable code I have for a 'gate' class (which I use in my own
> > programs) starts off with the gate closed, and it has a very simple
> > interface:
> > (1) you can open it
> > (2) you can close it
> > (3) you can wait for it to open
> > (4) you can wait for it to close
>
> You're describing a pair of std::binary_semaphore.
> https://en.cppreference.com/w/cpp/thread/counting_semaphore


That's too complicated in more than one way:

(1) It's too complicated in the English terminology used (i.e. talking
about semaphores and whether they're binary or not -- when all we want
is a simple gate)
(2) It's too complicated in terms of class types and template parameters
(3) It's too complicated to be managing two distinct objects instead of one

I mean really who wants code like as follows?

    pair<binary_semaphore> pbs;

    // main thread
    pbs.first.acquire();
    pbs.second.release();

    // worker thread
    pbs.first.release();
    pbs.second.acquire();

I've taken the code you linked me to on "cppreference.com", and I've
replaced the two binary_semaphore's with a 'gate' as follows:

#include <iostream>
#include <thread>
#include <chrono>

Gate gate;

void ThreadProc()
{
    // wait for a signal from the main proc
    gate.wait_for_open();

    std::cout << "[thread] Got the signal\n"; // response message

    // wait for 3 seconds to imitate some work
    // being done by the thread
    using namespace std::literals;
    std::this_thread::sleep_for(3s);

    std::cout << "[thread] Send the signal\n"; // message

    // signal the main proc back
    gate.close();
}

int main()
{
    // create some worker thread
    std::thread thrWorker(ThreadProc);

    std::cout << "[main] Send the signal\n"; // message

    // signal the worker thread to start working
    gate.open();

    // wait until the worker thread is done doing the work
    gate.wait_for_close();

    std::cout << "[main] Got the signal\n"; // response message
    thrWorker.join();
}

I realise that C++ is the programming language of choice for expert
programmers, and so one could argue that experts shouldn't have a
problem writing code for two binary_semaphore's -- but part of being
an expert at something is always stripping it down to the greatest
simplicity so that your brain can focus on other stuff.

And we should also take beginner programmers into account, there are
some beginners programmers who decide to start out in C++. Give them a
gate.

Messing around with two binary_semaphore's is nonsense, and if you're
working on a big project with a dozen other programmers, a bug will
creep in somewhere at some point (you'll get threadlock when somebody
does "pbs.first.acquire()" instead of "pbs.second.acquire()").

The C++ Standard library should have a simple 'gate'.

Received on 2022-07-22 09:49:18