Commit df5a2257 authored by Dominik Charousset's avatar Dominik Charousset

Prevent possible deadlock in singletons handling

By giving each singleton its own mutex, we remove a possible deadlock in the
singleton instantiation.
parent ffffab47
...@@ -75,22 +75,22 @@ class singletons { ...@@ -75,22 +75,22 @@ class singletons {
// usually guarded by implementation-specific singleton getter // usually guarded by implementation-specific singleton getter
template <class Factory> template <class Factory>
static abstract_singleton* get_plugin_singleton(size_t id, Factory f) { static abstract_singleton* get_plugin_singleton(size_t id, Factory f) {
return lazy_get(get_plugin_singleton(id), f); return lazy_get(get_plugin_singleton(id), get_plugin_mutex(), f);
} }
static void stop_singletons(); static void stop_singletons();
private: private:
static std::mutex& get_mutex(); static std::mutex& get_plugin_mutex();
static std::atomic<abstract_singleton*>& get_plugin_singleton(size_t id); static std::atomic<abstract_singleton*>& get_plugin_singleton(size_t id);
// Get instance from @p ptr or crate it on-the-fly using DCLP // Get instance from @p ptr or crate it on-the-fly using DCLP
template <class T, class Factory> template <class T, class Factory>
static T* lazy_get(std::atomic<T*>& ptr, Factory f) { static T* lazy_get(std::atomic<T*>& ptr, std::mutex& mtx, Factory f) {
auto result = ptr.load(std::memory_order_acquire); auto result = ptr.load(std::memory_order_acquire);
if (result == nullptr) { if (result == nullptr) {
std::lock_guard<std::mutex> guard(get_mutex()); std::lock_guard<std::mutex> guard(mtx);
result = ptr.load(std::memory_order_relaxed); result = ptr.load(std::memory_order_relaxed);
if (result == nullptr) { if (result == nullptr) {
result = f(); result = f();
...@@ -102,8 +102,8 @@ class singletons { ...@@ -102,8 +102,8 @@ class singletons {
} }
template <class T> template <class T>
static T* lazy_get(std::atomic<T*>& ptr) { static T* lazy_get(std::atomic<T*>& ptr, std::mutex& mtx) {
return lazy_get(ptr, [] { return T::create_singleton(); }); return lazy_get(ptr, mtx, [] { return T::create_singleton(); });
} }
template <class T> template <class T>
......
...@@ -35,15 +35,26 @@ namespace detail { ...@@ -35,15 +35,26 @@ namespace detail {
namespace { namespace {
std::mutex s_singletons_mtx;
std::atomic<abstract_singleton*> s_plugins[singletons::max_plugins]; std::atomic<abstract_singleton*> s_plugins[singletons::max_plugins];
std::mutex s_plugins_mtx;
std::atomic<scheduler::abstract_coordinator*> s_scheduling_coordinator; std::atomic<scheduler::abstract_coordinator*> s_scheduling_coordinator;
std::mutex s_scheduling_coordinator_mtx;
std::atomic<uniform_type_info_map*> s_uniform_type_info_map; std::atomic<uniform_type_info_map*> s_uniform_type_info_map;
std::mutex s_uniform_type_info_map_mtx;
std::atomic<actor_registry*> s_actor_registry; std::atomic<actor_registry*> s_actor_registry;
std::mutex s_actor_registry_mtx;
std::atomic<group_manager*> s_group_manager; std::atomic<group_manager*> s_group_manager;
std::mutex s_group_manager_mtx;
std::atomic<node_id::data*> s_node_id; std::atomic<node_id::data*> s_node_id;
std::mutex s_node_id_mtx;
std::atomic<logging*> s_logger; std::atomic<logging*> s_logger;
std::mutex s_logger_mtx;
} // namespace <anonymous> } // namespace <anonymous>
...@@ -51,8 +62,8 @@ abstract_singleton::~abstract_singleton() { ...@@ -51,8 +62,8 @@ abstract_singleton::~abstract_singleton() {
// nop // nop
} }
std::mutex& singletons::get_mutex() { std::mutex& singletons::get_plugin_mutex() {
return s_singletons_mtx; return s_plugins_mtx;
} }
void singletons::stop_singletons() { void singletons::stop_singletons() {
...@@ -84,31 +95,33 @@ void singletons::stop_singletons() { ...@@ -84,31 +95,33 @@ void singletons::stop_singletons() {
} }
actor_registry* singletons::get_actor_registry() { actor_registry* singletons::get_actor_registry() {
return lazy_get(s_actor_registry); return lazy_get(s_actor_registry, s_actor_registry_mtx);
} }
uniform_type_info_map* singletons::get_uniform_type_info_map() { uniform_type_info_map* singletons::get_uniform_type_info_map() {
return lazy_get(s_uniform_type_info_map); return lazy_get(s_uniform_type_info_map, s_uniform_type_info_map_mtx);
} }
group_manager* singletons::get_group_manager() { group_manager* singletons::get_group_manager() {
return lazy_get(s_group_manager); return lazy_get(s_group_manager, s_group_manager_mtx);
} }
scheduler::abstract_coordinator* singletons::get_scheduling_coordinator() { scheduler::abstract_coordinator* singletons::get_scheduling_coordinator() {
return lazy_get(s_scheduling_coordinator); return lazy_get(s_scheduling_coordinator, s_scheduling_coordinator_mtx);
} }
bool singletons::set_scheduling_coordinator(scheduler::abstract_coordinator*p) { bool singletons::set_scheduling_coordinator(scheduler::abstract_coordinator*p) {
return lazy_get(s_scheduling_coordinator, [p] { return p; }) == p; auto res = lazy_get(s_scheduling_coordinator, s_scheduling_coordinator_mtx,
[p] { return p; });
return res == p;
} }
node_id singletons::get_node_id() { node_id singletons::get_node_id() {
return node_id{lazy_get(s_node_id)}; return node_id{lazy_get(s_node_id, s_node_id_mtx)};
} }
logging* singletons::get_logger() { logging* singletons::get_logger() {
return lazy_get(s_logger); return lazy_get(s_logger, s_logger_mtx);
} }
std::atomic<abstract_singleton*>& singletons::get_plugin_singleton(size_t id) { std::atomic<abstract_singleton*>& singletons::get_plugin_singleton(size_t id) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment