EnTT 3.14.0
|
Usually, service locators are tightly bound to the services they expose and it's hard to define a general purpose solution.
This tiny class tries to fill the gap and gets rid of the burden of defining a different specific locator for each application.
The service locator API tries to mimic that of std::optional
and adds some extra functionalities on top of it such as allocator support.
There are a couple of functions to set up a service, namely emplace
and allocate_emplace
:
The difference is that the latter expects an allocator as the first argument and uses it to allocate the service itself.
Once a service is set up, it's retrieved using the value
function:
Since the service may not be set (and therefore this function may result in an undefined behavior), the has_value
and value_or
functions are also available to test a service locator and to get a fallback service in case there is none:
All arguments are used only if necessary, that is, if a service doesn't already exist and therefore the fallback service is constructed and returned. In all other cases, they are discarded.
Finally, to reset a service, use the reset
function.
Sometimes it's useful to transfer a copy of a service to another locator. For example, when working across boundaries it's common to share a service with a dynamically loaded module.
Options aren't much in this case. Among these is the possibility of exporting services and assigning them to a different locator.
This is what the handle
and reset
functions are meant for.
The former returns an opaque object useful for exporting (or rather, obtaining a reference to) a service. The latter also accepts an optional argument to a handle which then allows users to reset a service by initializing it with an opaque handle:
It's worth noting that it's possible to get handles for uninitialized services and use them with other locators. Of course, all a user will get is to have an uninitialized service elsewhere as well.
Note that exporting a service allows users to share the object currently set in a locator. Replacing it won't replace the element even where a service has been configured with a handle to the previous item.
In other words, if an audio service is replaced with a null object to silence an application and the original service was shared, this operation won't propagate to the other locators. Therefore, a module that share the ownership of the original audio service is still able to emit sounds.