Consolix
Loading...
Searching...
No Matches
ServiceLocator.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _CONSOLIX_SERVICE_LOCATOR_HPP_INCLUDED
3#define _CONSOLIX_SERVICE_LOCATOR_HPP_INCLUDED
4
8
9#if CONSOLIX_USE_LOGIT == 1
10#include <log-it/LogIt.hpp>
11#endif
12
13#include <unordered_map>
14#include <functional>
15#include <memory>
16#include <typeindex>
17#include <stdexcept>
18#include <shared_mutex>
19#include <mutex>
20
21namespace consolix {
22
29 public:
30
34 static ServiceLocator* instance = new ServiceLocator();
35 return *instance;
36 }
37
42 template <typename T>
43 void register_service(std::function<std::shared_ptr<T>()> creator) {
44 std::unique_lock<std::shared_mutex> lock(m_mutex);
45 const auto type = std::type_index(typeid(T));
46 if (m_services.find(type) != m_services.end()) {
47# if CONSOLIX_USE_LOGIT == 1
48 LOGIT_PRINT_ERROR("Service already registered: ", std::string(typeid(T).name()));
49# endif
50 throw std::runtime_error("Service already registered: " + std::string(typeid(T).name()));
51 }
52 lock.unlock();
53 auto ptr = creator();
54 lock.lock();
55 m_services[type] = std::move(ptr);
56 }
57
61 template <typename T>
63 std::unique_lock<std::shared_mutex> lock(m_mutex);
64 const auto type = std::type_index(typeid(T));
65 if (m_services.find(type) != m_services.end()) {
66# if CONSOLIX_USE_LOGIT == 1
67 LOGIT_PRINT_ERROR("Service already registered: ", std::string(typeid(T).name()));
68# endif
69 throw std::runtime_error("Service already registered: " + std::string(typeid(T).name()));
70 }
71 m_services[type] = std::make_shared<T>();
72 }
73
78 template <typename T>
80 std::shared_lock<std::shared_mutex> lock(m_mutex);
81 const auto type = std::type_index(typeid(T));
82 auto it = m_services.find(type);
83 if (it == m_services.end()) {
84# if CONSOLIX_USE_LOGIT == 1
85 LOGIT_PRINT_ERROR("Service not registered: ", std::string(typeid(T).name()));
86# endif
87 throw std::runtime_error("Service not registered: " + std::string(typeid(T).name()));
88 }
89 return *std::static_pointer_cast<T>(it->second);
90 }
91
95 template <typename T>
96 bool has_service() {
97 std::shared_lock<std::shared_mutex> lock(m_mutex);
98 const auto type_id = std::type_index(typeid(T));
99 return m_services.find(type_id) != m_services.end();
100 }
101
103 void clear_all() {
104 std::unique_lock<std::shared_mutex> lock(m_mutex);
105 m_services.clear();
106 }
107
108 private:
109 std::unordered_map<
110 std::type_index,
111 std::shared_ptr<void>> m_services;
112 std::shared_mutex m_mutex;
113
114 ServiceLocator() = default;
115 ~ServiceLocator() = default;
116
117 // Delete copy and move constructors and assignment operators.
122 }; // ServiceLocator
123
124} // namespace consolix
125
126#endif // _CONSOLIX_SERVICE_LOCATOR_HPP_INCLUDED
static ServiceLocator & get_instance()
Retrieves the singleton instance of the ServiceLocator.
void clear_all()
Clears all registered resources.
ServiceLocator(ServiceLocator &&)=delete
void register_service(std::function< std::shared_ptr< T >()> creator)
Registers a resource or service.
std::unordered_map< std::type_index, std::shared_ptr< void > > m_services
Registered services.
bool has_service()
Checks if a resource is registered.
ServiceLocator & operator=(const ServiceLocator &)=delete
T & get_service()
Retrieves a resource from the locator.
std::shared_mutex m_mutex
Mutex for thread-safe access.
void register_service()
Registers a resource with default construction.
ServiceLocator(const ServiceLocator &)=delete
ServiceLocator & operator=(ServiceLocator &&)=delete
< Utility modules and helpers.