mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-28 15:17:46 +00:00
112 lines
3.3 KiB
C++
112 lines
3.3 KiB
C++
#pragma once
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
#include <cassert>
|
|
|
|
// stolen from: https://github.com/skypjack/entt/blob/master/src/entt/locator/locator.hpp
|
|
|
|
namespace Sapphire::Common
|
|
{
|
|
/**
|
|
* @brief Service locator, nothing more.
|
|
*
|
|
* A service locator can be used to do what it promises: locate services.<br/>
|
|
* Usually service locators are tightly bound to the services they expose and
|
|
* thus it's hard to define a general purpose class to do that. This template
|
|
* based implementation tries to fill the gap and to get rid of the burden of
|
|
* defining a different specific locator for each application.
|
|
*
|
|
* @tparam SvcType Type of service managed by the locator.
|
|
*/
|
|
template< typename SvcType >
|
|
struct Service
|
|
{
|
|
/*! @brief Type of service offered. */
|
|
using ServiceType = SvcType;
|
|
|
|
/*! @brief Default constructor, deleted on purpose. */
|
|
Service() = delete;
|
|
|
|
/*! @brief Default destructor, deleted on purpose. */
|
|
~Service() = delete;
|
|
|
|
/**
|
|
* @brief Tests if a valid service implementation is set.
|
|
* @return True if the service is set, false otherwise.
|
|
*/
|
|
static bool empty() noexcept
|
|
{
|
|
return !static_cast< bool >( service );
|
|
}
|
|
|
|
/**
|
|
* @brief Returns a weak pointer to a service implementation, if any.
|
|
*
|
|
* Clients of a service shouldn't retain references to it. The recommended
|
|
* way is to retrieve the service implementation currently set each and
|
|
* every time the need of using it arises. Otherwise users can incur in
|
|
* unexpected behaviors.
|
|
*
|
|
* @return A reference to the service implementation currently set, if any.
|
|
*/
|
|
static std::weak_ptr< SvcType > get() noexcept
|
|
{
|
|
return service;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns a weak reference to a service implementation, if any.
|
|
*
|
|
* Clients of a service shouldn't retain references to it. The recommended
|
|
* way is to retrieve the service implementation currently set each and
|
|
* every time the need of using it arises. Otherwise users can incur in
|
|
* unexpected behaviors.
|
|
*
|
|
* @warning
|
|
* In case no service implementation has been set, a call to this function
|
|
* results in undefined behavior.
|
|
*
|
|
* @return A reference to the service implementation currently set, if any.
|
|
*/
|
|
static SvcType& ref() noexcept
|
|
{
|
|
return *service;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets or replaces a service.
|
|
* @tparam Impl Type of the new service to use.
|
|
* @tparam Args Types of arguments to use to construct the service.
|
|
* @param args Parameters to use to construct the service.
|
|
*/
|
|
template< typename Impl = SvcType, typename... Args >
|
|
static void set( Args&& ... args )
|
|
{
|
|
service = std::make_shared< Impl >( std::forward< Args >( args )... );
|
|
}
|
|
|
|
/**
|
|
* @brief Sets or replaces a service.
|
|
* @param ptr Service to use to replace the current one.
|
|
*/
|
|
static void set( std::shared_ptr< SvcType > ptr )
|
|
{
|
|
assert( static_cast< bool >( ptr ) );
|
|
service = std::move( ptr );
|
|
}
|
|
|
|
/**
|
|
* @brief Resets a service.
|
|
*
|
|
* The service is no longer valid after a reset.
|
|
*/
|
|
static void reset()
|
|
{
|
|
service.reset();
|
|
}
|
|
|
|
private:
|
|
inline static std::shared_ptr< SvcType > service = nullptr;
|
|
};
|
|
}
|