C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Callsite passed as template parameter

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Fri, 17 Nov 2023 13:50:10 +0000
On Wednesday, November 15, 2023, Frederick Virchanza Gotham wrote:

>
> This would be very useful for data logging, or for implementing
> functions that work along the same lines as 'strtok'.
>


I've thought of a really good use for this.

I have a program running a superloop on an Arduino microcontroller. In
order to keep the iteration time of the superloop below 100 milliseconds, I
only allow it to send one message per iteration of the superloop.

To send a message, I call:

    gSimGsm.send("whatever");

which will return true if it sent a message, or return false if it failed
because there had already been one message sent in that iteration of the
superloop.

And so I wrote a class called SuperloopManager, which you can use as
follows:

    gSuperloopManager.DeferUntilTrue([]{ send("whatever"); });

The above line of code will immediately try to send a message, but if it
cannot because there has already been a message sent in the current
iteration of the superloop, then it will defer it until the next iteration.
It will keep invoking that lambda upon each iteration of the superloop
until the lambda returns true.

But the problem is that if the message keeps getting deferred again and
again and again, then the program might reach a point where it enqueues the
same message a second time. Then we'll have two of the same message waiting
in the queue, and if it happens a third time and a fourth time then the
queue will become full and my microcontroller will reset.

To remedy this, I was considering putting a unique ID at every callsite,
something like:

    enum { msg_monkey, msg_donkey, msg_goat };

    gSuperloopManager.DeferUntilTrue(msg_monkey, []{ send("whatever"); });

And then I would check the ID to ensure that the message in question isn't
already in the queue.

But it would be more convenient to do:

    class SuperloopManager {
        template<typename = decltype([]{})>
        void DeferUntilTrue(std::function<void(void)> &&arg)
        {
            static char dummy;

            // code here
        }
    };

And then I could use the address of 'dummy' as a compile-time constant to
identify the message and to disallow a double-queuing.

Received on 2023-11-17 13:50:13