MySQL 9.1.0
Source Code Documentation
weak_service_reference< Service, container, service_name > Class Template Reference

A utility class to implement a delayed service reference. More...

#include <weak_service_reference.h>

Static Public Member Functions

static bool init (const mysql_service_registry_t *reg_arg, const mysql_service_registry_registration_t *reg_reg_arg, std::function< bool(Service *)> func_arg, bool keep_active_reference_arg=true)
 Initialize the weak reference class. More...
 
static bool deinit (const mysql_service_registry_t *registry_arg, const mysql_service_registry_registration_t *registry_registration_arg, std::function< bool(Service *)> deinit_func_arg)
 Deinitializes a weak reference caller class. More...
 

Private Member Functions

 weak_service_reference (std::function< bool(Service *)> &func_arg)
 A private constructor for the hton. More...
 

Static Private Member Functions

static bool call_function ()
 Helper function to take a reference to the service needed and call the init callback function. More...
 
static mysql_service_status_t notify (const char **services, unsigned int count) noexcept
 An implementation for the dynamic_loader_services_loaded_notification::notify service method. More...
 

Private Attributes

std::atomic< bool > function_called {false}
 A flag if the init callback function has been called. More...
 
const std::function< bool(Service *)> function
 The init callback reference. More...
 
std::string listener_name
 A service_loaded listener implementation name of the following format: dynamic_loader_services_loaded_notification. More...
 
my_service< Service > service_reference
 

Static Private Attributes

static weak_service_reference< Service, container, service_name > * hton
 A single instance of the class to hold (and initialize) some data at init time. More...
 
static const mysql_service_registry_tregistry {nullptr}
 We need to store a reference to the registry since the init callback needs it. More...
 
static bool callback_registered {false}
 A flag stating if the callback service implementation listening for new implementations of the service has been registered. More...
 
static bool keep_active_reference {true}
 true when the weak reference class is to keep the reference acquired for reuse until deinit is called. More...
 

Detailed Description

template<typename Service, const std::string & container, const std::string & service_name>
class weak_service_reference< Service, container, service_name >

A utility class to implement a delayed service reference.

This class allows a component to have a "weak" reference to a component service.

Operation in default mode (keep references = true)
In its default mode (keep references) when the weak reference is initialized the class checks if the service required already has implementations. If it does, the class takes a reference to the default one, calls the supplied function and keeps the reference. If there's no implementation of the service the class registers a listener to the dynamic_loader_services_loaded_notification broadcast service by implementing a dynamic_loader_services_loaded_notification service that, when called by the dynamic loader, will take a reference to the desired service, call the function supplied and keep the reference until deinit. And then it sets a flag preventing any further calls to the function.
At deinit time, if there's an active reference, deinit calls the supplied function and passes it as a parameter. And then releases the reference. Otherwise, no call of the supplied deinit function is done. It also unregisters the dynamic_loader_services_loaded_notification callback, if registered.
Operation in do-not-keep-references mode.
When the weak reference is initialized the class checks if the service required already has implementations. If it does, then the class takes a reference to the default implementation, calls the supplied init function and releases the reference. It then proceeds to unconditioanlly register a listener to the dynamic_loader_services_loaded_notification broadcast service by implementing a dynamic_loader_services_loaded_notification service that, when called by the dynamic loader, will take a reference to the desired service, call the function supplied and then release the reference. Every time a new implementation is registered, the notification callback will be called so the weak reference can re-register itself again.
At deinit time, deinit tries to acquire the required service and, if successful, calls the supplied deinit function and passes it as a parameter. Note that if the service implementation has been undefined in the meanwhile no call of the supplied deinit function is done.
Warning
Do not use the do-not-keep-references mode for anyting but the server! It is only justified for the server component (aka the bootstrap component) because if it doesn't use it no one will be able to unload the component implementing the service once captured by the bootstrap component. Yes, unloading service implementation component would be impossible, but that's a desired side effect since there is state that needs to be destroyed properly before the service implementation can be unloaded.

Normal usage pattern is that the weak_service_reference::init() is called during component initialization.

And weak_service_reference::deinit() is called during the component deinitialization.

Warning
Please pass the _no_lock registry variants to the deinit() call! It's because component deinit function is called while the registry lock is held. So trying to take the lock again (which is what the normal registry functions do) is going to lead to a deadlock!

One can expect that the function argument is called either at init() time or asyncronously, possibly from anoher thread, when an implementation of a service is registered.

Typical usage:

...
#include "mysql/components/services/foo.h"
...
REQUIRES_SERVICE_PLACEHOLDER(registry_registration);
REQUIRES_SERVICE_PLACEHOLDER_AS(registry, mysql_service_registry_no_lock);
mysql_service_registration_no_lock);
const std::string c_name(component_foo), s_name("foo");
weak_foo_service;
...
mysql_minimal_chassis_no_lock,
mysql_service_registration_no_lock),
REQUIRES_SERVICE_IMPLEMENTATION_AS(registry, mysql_minimal_chassis_no_lock,
mysql_service_registry_no_lock),
...
END_COMPONENT_REQUIRES();
bool component_init() {
...
[&](SERVICE_TYPE(foo) * foo_svc) {
return 0 != foo_svc->define(12);
}))
return 1;
...
}
bool component_deinit() {
...
mysql_service_registry_no_lock, mysql_service_registration_no_lock,
[&](SERVICE_TYPE(foo) * foo_svc) {
return 0 != foo_svc->undefine(12);
}))
return 1;
static mysql_service_status_t init()
Component initialization.
Definition: audit_api_message_emit.cc:571
A utility class to implement a delayed service reference.
Definition: weak_service_reference.h:166
static const mysql_service_registry_t * registry
We need to store a reference to the registry since the init callback needs it.
Definition: weak_service_reference.h:178
static bool deinit(const mysql_service_registry_t *registry_arg, const mysql_service_registry_registration_t *registry_registration_arg, std::function< bool(Service *)> deinit_func_arg)
Deinitializes a weak reference caller class.
Definition: weak_service_reference.h:352
#define BEGIN_COMPONENT_REQUIRES(name)
A macro to specify requirements of the component.
Definition: component_implementation.h:223
#define REQUIRES_SERVICE(service)
Adds a Service requirement with a pointer to placeholder to the list of components.
Definition: component_implementation.h:305
#define REQUIRES_SERVICE_PLACEHOLDER_AS(service, name)
Create a service placeholder, with an arbitrary name.
Definition: component_implementation.h:296
#define SERVICE_PLACEHOLDER(service)
Use this macro to reference the service placeholder as defined by the REQUIRES_SERVICE_PLACEHOLDER ma...
Definition: component_implementation.h:382
#define REQUIRES_SERVICE_IMPLEMENTATION_AS(service, implementation, name)
Adds a Service implementation requirement with a pointer to placeholder to the list of components.
Definition: component_implementation.h:354
const std::string c_name("component_keyring_file")
static const std::string s_name("mysql_option_tracker_option")
const mysql_service_registry_registration_t * registry_registration
#define SERVICE_TYPE(name)
Generates the standard Service type name.
Definition: service.h:76
Template Parameters
ServiceThis is the type of the service to be called. E.g. SERVICE_TYPE(foo)
containerThe name of the "container". Usually a component name. It has to be a rvalue ref since you would need a distinct set of the static members of the template class for every service/component combo.
service_nameThe name of the service to try to call. It has to be a rvalue ref since you would need a distinct set of the static members of the template class for every service/component combo.

Constructor & Destructor Documentation

◆ weak_service_reference()

template<typename Service , const std::string & container, const std::string & service_name>
weak_service_reference< Service, container, service_name >::weak_service_reference ( std::function< bool(Service *)> &  func_arg)
inlineprivate

A private constructor for the hton.

Parameters
func_argThe function to call when there's an implementation. active reference until deinit.

Member Function Documentation

◆ call_function()

template<typename Service , const std::string & container, const std::string & service_name>
static bool weak_service_reference< Service, container, service_name >::call_function ( )
inlinestaticprivate

Helper function to take a reference to the service needed and call the init callback function.

Return values
truefailure
falsesuccess

◆ deinit()

template<typename Service , const std::string & container, const std::string & service_name>
static bool weak_service_reference< Service, container, service_name >::deinit ( const mysql_service_registry_t registry_arg,
const mysql_service_registry_registration_t registry_registration_arg,
std::function< bool(Service *)>  deinit_func_arg 
)
inlinestatic

Deinitializes a weak reference caller class.

If the init callback was called it will try to acquire a reference to the service and call the deinit callback if the reference is acquired.

Then it will deregister the dynamic_loader_services_loaded_notification implementation, if it's been registered by init().

And it will then proceed to delete the state in hton and reset the class.

Parameters
registry_argA reference to the registry service implementation
registry_registration_argA reference to the registry_registration service implementation
deinit_func_argA (deinit) function to call if an implementation of the service required is definied. One typically reverses the action taken by the registration callback here, e.g. diposes of state, deregisters features etc.
Return values
truefailure
falsesuccess

◆ init()

template<typename Service , const std::string & container, const std::string & service_name>
static bool weak_service_reference< Service, container, service_name >::init ( const mysql_service_registry_t reg_arg,
const mysql_service_registry_registration_t reg_reg_arg,
std::function< bool(Service *)>  func_arg,
bool  keep_active_reference_arg = true 
)
inlinestatic

Initialize the weak reference class.

Parameters
reg_argA reference to the registry service implementation
reg_reg_argA reference to the registry_registration service implementation
func_argA function to be called when an implementation of the service is available. Typically used to initialize some state, e.g. allocate instance handles or register some features in registries.
keep_active_reference_argTrue if weak_reference is to keep an active reference until deinit.

This is typically called by the component initialization. If there's already an implementation of the service required a reference to it is obtained and is passed to the function callback from the argument.

If no implementations are available a listener for new implementation registration (an implementation of the dynamic_loader_services_loaded_notifications service) is registered into the registry and the function returns.

Note
Pass the "normal" references to the registry and the registry registration services here. init() is called without any locks being held to the registry.
Return values
trueFailure
falseSuccess

◆ notify()

template<typename Service , const std::string & container, const std::string & service_name>
static mysql_service_status_t weak_service_reference< Service, container, service_name >::notify ( const char **  services,
unsigned int  count 
)
inlinestaticprivatenoexcept

An implementation for the dynamic_loader_services_loaded_notification::notify service method.

This is called by the dynamic loader when a new service implementation is registered.

Member Data Documentation

◆ callback_registered

template<typename Service , const std::string & container, const std::string & service_name>
bool weak_service_reference< Service, container, service_name >::callback_registered {false}
inlinestaticprivate

A flag stating if the callback service implementation listening for new implementations of the service has been registered.

◆ function

template<typename Service , const std::string & container, const std::string & service_name>
const std::function<bool(Service *)> weak_service_reference< Service, container, service_name >::function
private

The init callback reference.

◆ function_called

template<typename Service , const std::string & container, const std::string & service_name>
std::atomic<bool> weak_service_reference< Service, container, service_name >::function_called {false}
private

A flag if the init callback function has been called.

This is to prevent multiple calls to the init callback. Ideally we'd unregister the callback altogether, but the callback is called while a reference to it is held, so it can't unregister itself due to an active reference. Hence we raise the flag to prevent further action and deregister at deinit()

◆ hton

template<typename Service , const std::string & container, const std::string & service_name>
weak_service_reference<Service, container, service_name>* weak_service_reference< Service, container, service_name >::hton
inlinestaticprivate
Initial value:
{
nullptr}

A single instance of the class to hold (and initialize) some data at init time.

◆ keep_active_reference

template<typename Service , const std::string & container, const std::string & service_name>
bool weak_service_reference< Service, container, service_name >::keep_active_reference {true}
inlinestaticprivate

true when the weak reference class is to keep the reference acquired for reuse until deinit is called.

◆ listener_name

template<typename Service , const std::string & container, const std::string & service_name>
std::string weak_service_reference< Service, container, service_name >::listener_name
private

A service_loaded listener implementation name of the following format: dynamic_loader_services_loaded_notification.

<conainer_name>_<service_name>

◆ registry

template<typename Service , const std::string & container, const std::string & service_name>
const mysql_service_registry_t* weak_service_reference< Service, container, service_name >::registry {nullptr}
inlinestaticprivate

We need to store a reference to the registry since the init callback needs it.

◆ service_reference

template<typename Service , const std::string & container, const std::string & service_name>
my_service<Service> weak_service_reference< Service, container, service_name >::service_reference
private

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