Flow 3.0.0
Flow project: Public API.
Public Types | Static Public Member Functions | List of all members
flow::util::Action_registry< Tag_t, Args > Class Template Reference

A registry of callbacks (actions) sharing a common signature, intended for fan-out invocation across statically-constructed singletons. More...

#include <action_registry.hpp>

Public Types

using Tag = Tag_t
 Alias for template parameter.
 

Static Public Member Functions

template<typename Action_func >
static void register_action (Action_func &&action)
 Registers a callback to be invoked by future execute() calls. More...
 
static void execute (const Args &... args)
 Invokes every registered callback, in registration order, passing the given arguments to each. More...
 

Detailed Description

template<typename Tag_t, typename... Args>
class flow::util::Action_registry< Tag_t, Args >

A registry of callbacks (actions) sharing a common signature, intended for fan-out invocation across statically-constructed singletons.

Each singleton self-registers a callback during its static construction; the end user then invokes execute() once to fan out to all registered callbacks.

It is possible, and fine, to register actions from places other than singleton initializers, and the action itself is in no way required to do something singleton- or even global-related. The original motivation was for singleton self-registration, but conceivably Action_registry can be useful elsewhere.

Motivation

Consider a framework with multiple singleton subsystems, each needing a set_logger() call at startup and teardown. Without Action_registry the user must know about and call each one; and a new subsystem (possibly from a downstream project) cannot participate without modifying the framework's central code. With Action_registry each singleton registers itself, and the user's single execute() call reaches all of them – including ones the framework author never anticipated.

Usage

Define a tag type to differentiate your registry from others:

struct My_set_logger_tag {};
A registry of callbacks (actions) sharing a common signature, intended for fan-out invocation across ...
Definition: action_registry.hpp:98

Each singleton registers during construction:

// In some singleton's static-init context (ctor, Static_state ctor, etc.):
My_set_logger_registry::register_action([](flow::log::Logger* logger_ptr)
{
Foo::static_set_logger(logger_ptr);
});
Interface that the user should implement, passing the implementing Logger into logging classes (Flow'...
Definition: log.hpp:1392

The end user simply does:

My_set_logger_registry::execute(&my_logger); // startup
// Forwarded `&my_logger` to all registered actions: Executed them in order of registration.
// ... application runs ...
My_set_logger_registry::execute(nullptr); // teardown
// Forwarded `nullptr` to all registered actions: Executed them in order of registration.

Arg types

Each type in Args shall be a plain non-reference, non-const type – typically a pointer or scalar. (Pointer to const is perfectly fine: e.g., const Logger*.) execute() receives each arg by const reference and passes it, as an lvalue, to each registered callback; since the callback signature takes Args by value, a copy is made per callback invocation. For pointer/scalar types this cost is trivial. For heavier types, prefer passing a pointer to the heavy object rather than the object itself.

Thread safety

All methods are thread-safe with respect to each other. Internally a non-recursive mutex is held during both register_action() and execute(). Consequently a callback invoked by execute() must not call register_action() on the same Action_registry instantiation; doing so will deadlock (this is intentional: such a call pattern would indicate a design problem).

Template Parameters
Tag_tA tag type used solely to differentiate distinct Action_registry instantiations. Each unique Tag yields a distinct singleton registry.
ArgsThe parameter types of the action. Each registered callback has signature void (Args...). See "Arg types" above.

Member Function Documentation

◆ execute()

template<typename Tag_t , typename... Args>
void flow::util::Action_registry< Tag_t, Args >::execute ( const Args &...  args)
static

Invokes every registered callback, in registration order, passing the given arguments to each.

Thread-safe.

Parameters
argsArguments forwarded to each registered callback.

◆ register_action()

template<typename Tag_t , typename... Args>
template<typename Action_func >
void flow::util::Action_registry< Tag_t, Args >::register_action ( Action_func &&  action)
static

Registers a callback to be invoked by future execute() calls.

Intended to be called from singleton constructors (static-init time or lazy-init get_instance() patterns). Thread-safe.

Template Parameters
Action_funcFunctor type matching the signature void (Args...).
Parameters
actionThe callback to register. Must not be empty.

The documentation for this class was generated from the following file: