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 {
// usually guarded by implementation-specific singleton getter
template <class Factory>
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();
private:
static std::mutex& get_mutex();
static std::mutex& get_plugin_mutex();
static std::atomic<abstract_singleton*>& get_plugin_singleton(size_t id);
// Get instance from @p ptr or crate it on-the-fly using DCLP
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);
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);
if (result == nullptr) {
result = f();
......@@ -102,8 +102,8 @@ class singletons {
}
template <class T>
static T* lazy_get(std::atomic<T*>& ptr) {
return lazy_get(ptr, [] { return T::create_singleton(); });
static T* lazy_get(std::atomic<T*>& ptr, std::mutex& mtx) {
return lazy_get(ptr, mtx, [] { return T::create_singleton(); });
}
template <class T>
......
......@@ -35,15 +35,26 @@ namespace detail {
namespace {
std::mutex s_singletons_mtx;
std::atomic<abstract_singleton*> s_plugins[singletons::max_plugins];
std::mutex s_plugins_mtx;
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::mutex s_uniform_type_info_map_mtx;
std::atomic<actor_registry*> s_actor_registry;
std::mutex s_actor_registry_mtx;
std::atomic<group_manager*> s_group_manager;
std::mutex s_group_manager_mtx;
std::atomic<node_id::data*> s_node_id;
std::mutex s_node_id_mtx;
std::atomic<logging*> s_logger;
std::mutex s_logger_mtx;
} // namespace <anonymous>
......@@ -51,8 +62,8 @@ abstract_singleton::~abstract_singleton() {
// nop
}
std::mutex& singletons::get_mutex() {
return s_singletons_mtx;
std::mutex& singletons::get_plugin_mutex() {
return s_plugins_mtx;
}
void singletons::stop_singletons() {
......@@ -84,31 +95,33 @@ void singletons::stop_singletons() {
}
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() {
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() {
return lazy_get(s_group_manager);
return lazy_get(s_group_manager, s_group_manager_mtx);
}
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) {
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() {
return node_id{lazy_get(s_node_id)};
return node_id{lazy_get(s_node_id, s_node_id_mtx)};
}
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) {
......
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