4

I wrote a function a while ago, based on Unreal Engine 4's blueprint implementation, that invokes a callable exactly once until it is reset:

template<typename Callable>
void DoOnce(Callable&& f, bool reset = false, bool start_closed = false) noexcept {
    static bool once = start_closed;
    if(!once) {
        once = true;
        std::invoke(f);
    }
    if(reset) {
        once = false;
    }
}

Today I learned std::call_once exists, works across threads, works with callables that have arguments, tests for exception-safety, and basically wraps around std::invoke like mine does (the MSVC implementation at least).

That sounds great and, where possible, I prefer calling a pre-existing function over writing my own anyway.

Like Unreal's documentaion suggests, there are times that I may need to invoke the callable again by resetting the internal flag; can std::call_once be reset in order to allow the underlying callable to be invoked again?

Casey
  • 10,297
  • 11
  • 59
  • 88
  • 2
    well, you can reset the flag by making a new one with placement-new . I don't see anything in the standard that would rule that out, although it smells a bit fishy – M.M Apr 28 '21 at 03:14

1 Answers1

4

The standard isn't kidding when they call it "once_flag". It's a flag that only gets set once.

You can of course call the function multiple times, with different once-flag objects. But to do this properly, you need to hand each thread that might attempt to call it the new once-flag object. It can't just be a global or static object somewhere; you have to actually marshal each new invocation out to all of the threads that want to call it.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • @Casey: Well, you're the one who's trying to `call_once` a thing *more than once*. Grossness is kind of expected ;) – Nicol Bolas Apr 28 '21 at 04:07
  • Call once looks like "magic statics, but without the statics" exposed by the standard to me. Like, `static const bool unused=(static_cast(f()),true);` without the noise. – Yakk - Adam Nevraumont Apr 28 '21 at 04:09
  • I'm accepting this as an answer, but on the understanding that it's a long-winded way to say: "No, that's not what it's used for." :) Using the STL or standard improperly is inviting disaster. – Casey Apr 29 '21 at 22:02