MySQL 9.0.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)
 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...
 

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...
 

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. 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 and calls the supplied function. 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 refernece to the desired service and call the function supplied. And then it sets a flag preventing any further calls to the function.

At deinit time, deinit tries to acquire the foo service and, if successful, calls the supplied function and passes it as a parameter. Note that if the service implementation has been undefined in the meanwhile no call of the deinit supplied function is done.

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 deinit()
Component deinitialization.
Definition: audit_api_message_emit.cc:580
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:133
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:145
#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
static const std::string c_name("mysql_server")
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.

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.
Returns
true
false

◆ 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 
)
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.

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.

◆ 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.


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