Commit 7deb370f authored by Dominik Charousset's avatar Dominik Charousset

Add a meta objects guard to the actor system

parent 4e70994d
...@@ -85,20 +85,6 @@ std::string get_rtti_from_mpi() { ...@@ -85,20 +85,6 @@ std::string get_rtti_from_mpi() {
namespace caf { namespace caf {
/// An opaque type for shared object lifetime management of the global meta
/// objects table.
using global_meta_objects_guard_type = intrusive_ptr<ref_counted>;
// Note: for technical reasons (dependencies), `global_meta_objects_guard` is
// implemented in src/detail/meta_object.cpp.
/// Returns a shared ownership wrapper for global state to manage meta objects.
/// Any thread that accesses the actor system should participate in the lifetime
/// management of the global state by using a meta objects guard.
/// @warning The guard does *not* extend the lifetime of the actor system.
/// @relates actor_system
CAF_CORE_EXPORT global_meta_objects_guard_type global_meta_objects_guard();
/// Actor environment including scheduler, registry, and optional components /// Actor environment including scheduler, registry, and optional components
/// such as a middleman. /// such as a middleman.
class CAF_CORE_EXPORT actor_system { class CAF_CORE_EXPORT actor_system {
...@@ -569,7 +555,11 @@ public: ...@@ -569,7 +555,11 @@ public:
f(); f();
thread_terminates(); thread_terminates();
}; };
return std::thread{std::move(body), global_meta_objects_guard()}; return std::thread{std::move(body), meta_objects_guard_};
}
auto meta_objects_guard() const noexcept {
return meta_objects_guard_;
} }
const auto& metrics_actors_includes() const noexcept { const auto& metrics_actors_includes() const noexcept {
...@@ -751,6 +741,9 @@ private: ...@@ -751,6 +741,9 @@ private:
/// Manages threads for detached actors. /// Manages threads for detached actors.
detail::private_thread_pool private_threads_; detail::private_thread_pool private_threads_;
/// Ties the lifetime of the meta objects table to the actor system.
detail::global_meta_objects_guard_type meta_objects_guard_;
}; };
} // namespace caf } // namespace caf
...@@ -240,9 +240,18 @@ struct IUnknown; ...@@ -240,9 +240,18 @@ struct IUnknown;
// Convenience macros. // Convenience macros.
#define CAF_IGNORE_UNUSED(x) static_cast<void>(x) #define CAF_IGNORE_UNUSED(x) static_cast<void>(x)
/// Prints `error` to `stderr` and aborts program execution.
#define CAF_CRITICAL(error) \ #define CAF_CRITICAL(error) \
do { \ do { \
fprintf(stderr, "[FATAL] %s:%u: critical error: '%s'\n", __FILE__, \ fprintf(stderr, "[FATAL] critical error (%s:%d): %s\n", __FILE__, \
__LINE__, error); \ __LINE__, error); \
::abort(); \ ::abort(); \
} while (false) } while (false)
/// Prints `error` to `stderr` and aborts program execution.
#define CAF_CRITICAL_FMT(fmt_str, ...) \
do { \
fprintf(stderr, "[FATAL] critical error (%s:%d): " fmt_str "\n", __FILE__, \
__LINE__, __VA_ARGS__); \
::abort(); \
} while (false)
...@@ -51,6 +51,15 @@ struct meta_object { ...@@ -51,6 +51,15 @@ struct meta_object {
void (*stringify)(std::string&, const void*); void (*stringify)(std::string&, const void*);
}; };
/// An opaque type for shared object lifetime management of the global meta
/// objects table.
using global_meta_objects_guard_type = intrusive_ptr<ref_counted>;
/// Returns a shared ownership wrapper for global state to manage meta objects.
/// Any thread that accesses the actor system should participate in the lifetime
/// management of the global state by using a meta objects guard.
CAF_CORE_EXPORT global_meta_objects_guard_type global_meta_objects_guard();
/// Returns the global storage for all meta objects. The ::type_id of an object /// Returns the global storage for all meta objects. The ::type_id of an object
/// is the index for accessing the corresonding meta object. /// is the index for accessing the corresonding meta object.
CAF_CORE_EXPORT span<const meta_object> global_meta_objects(); CAF_CORE_EXPORT span<const meta_object> global_meta_objects();
......
...@@ -361,6 +361,8 @@ CAF_CORE_EXPORT void intrusive_ptr_release(const dynamic_message_data*); ...@@ -361,6 +361,8 @@ CAF_CORE_EXPORT void intrusive_ptr_release(const dynamic_message_data*);
CAF_CORE_EXPORT dynamic_message_data* CAF_CORE_EXPORT dynamic_message_data*
intrusive_cow_ptr_unshare(dynamic_message_data*&); intrusive_cow_ptr_unshare(dynamic_message_data*&);
using global_meta_objects_guard_type = intrusive_ptr<ref_counted>;
} // namespace detail } // namespace detail
// -- weak pointer aliases ----------------------------------------------------- // -- weak pointer aliases -----------------------------------------------------
......
...@@ -277,6 +277,9 @@ actor_system::actor_system(actor_system_config& cfg) ...@@ -277,6 +277,9 @@ actor_system::actor_system(actor_system_config& cfg)
tracing_context_(cfg.tracing_context), tracing_context_(cfg.tracing_context),
private_threads_(this) { private_threads_(this) {
CAF_SET_LOGGER_SYS(this); CAF_SET_LOGGER_SYS(this);
meta_objects_guard_ = detail::global_meta_objects_guard();
if (!meta_objects_guard_)
CAF_CRITICAL("unable to obtain the global meta objects guard");
for (auto& hook : cfg.thread_hooks_) for (auto& hook : cfg.thread_hooks_)
hook->init(*this); hook->init(*this);
// Cache some configuration parameters for faster lookups at runtime. // Cache some configuration parameters for faster lookups at runtime.
......
...@@ -21,13 +21,7 @@ ...@@ -21,13 +21,7 @@
#include "caf/serializer.hpp" #include "caf/serializer.hpp"
#include "caf/span.hpp" #include "caf/span.hpp"
namespace caf { namespace caf::detail {
#define fatal(str) \
do { \
fprintf(stderr, "FATAL: " str "\n"); \
abort(); \
} while (false)
namespace { namespace {
...@@ -53,10 +47,6 @@ global_meta_objects_guard_type global_meta_objects_guard() { ...@@ -53,10 +47,6 @@ global_meta_objects_guard_type global_meta_objects_guard() {
return cleanup_helper; return cleanup_helper;
} }
} // namespace caf
namespace caf::detail {
span<const meta_object> global_meta_objects() { span<const meta_object> global_meta_objects() {
return {meta_objects, meta_objects_size}; return {meta_objects, meta_objects_size};
} }
...@@ -79,8 +69,8 @@ void clear_global_meta_objects() { ...@@ -79,8 +69,8 @@ void clear_global_meta_objects() {
span<meta_object> resize_global_meta_objects(size_t size) { span<meta_object> resize_global_meta_objects(size_t size) {
if (size <= meta_objects_size) if (size <= meta_objects_size)
fatal("resize_global_meta_objects called with a new size that does not " CAF_CRITICAL("resize_global_meta_objects called with a new size that does "
"grow the array"); "not grow the array");
auto new_storage = new meta_object[size]; auto new_storage = new meta_object[size];
std::copy(meta_objects, meta_objects + meta_objects_size, new_storage); std::copy(meta_objects, meta_objects + meta_objects_size, new_storage);
delete[] meta_objects; delete[] meta_objects;
...@@ -93,9 +83,9 @@ void set_global_meta_objects(type_id_t first_id, span<const meta_object> xs) { ...@@ -93,9 +83,9 @@ void set_global_meta_objects(type_id_t first_id, span<const meta_object> xs) {
auto new_size = first_id + xs.size(); auto new_size = first_id + xs.size();
if (first_id < meta_objects_size) { if (first_id < meta_objects_size) {
if (new_size > meta_objects_size) if (new_size > meta_objects_size)
fatal("set_global_meta_objects called with " CAF_CRITICAL("set_global_meta_objects called with "
"'first_id < meta_objects_size' and " "'first_id < meta_objects_size' and "
"'new_size > meta_objects_size'"); "'new_size > meta_objects_size'");
auto out = meta_objects + first_id; auto out = meta_objects + first_id;
for (const auto& x : xs) { for (const auto& x : xs) {
if (out->type_name.empty()) { if (out->type_name.empty()) {
...@@ -108,12 +98,10 @@ void set_global_meta_objects(type_id_t first_id, span<const meta_object> xs) { ...@@ -108,12 +98,10 @@ void set_global_meta_objects(type_id_t first_id, span<const meta_object> xs) {
// Get null-terminated strings. // Get null-terminated strings.
auto name1 = to_string(out->type_name); auto name1 = to_string(out->type_name);
auto name2 = to_string(x.type_name); auto name2 = to_string(x.type_name);
fprintf(stderr, CAF_CRITICAL_FMT("type ID %d already assigned to %s "
"FATAL: type ID %d already assigned to %s (tried to override " "(tried to override with %s)",
"with %s)\n", static_cast<int>(std::distance(meta_objects, out)),
static_cast<int>(std::distance(meta_objects, out)), name1.c_str(), name2.c_str());
name1.c_str(), name2.c_str());
abort();
} }
++out; ++out;
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/defaults.hpp" #include "caf/defaults.hpp"
#include "caf/detail/get_process_id.hpp" #include "caf/detail/get_process_id.hpp"
#include "caf/detail/meta_object.hpp"
#include "caf/detail/pretty_type_name.hpp" #include "caf/detail/pretty_type_name.hpp"
#include "caf/detail/set_thread_name.hpp" #include "caf/detail/set_thread_name.hpp"
#include "caf/intrusive/task_result.hpp" #include "caf/intrusive/task_result.hpp"
...@@ -651,7 +652,7 @@ void logger::start() { ...@@ -651,7 +652,7 @@ void logger::start() {
this->run(); this->run();
this->system_.thread_terminates(); this->system_.thread_terminates();
}; };
thread_ = std::thread{f, global_meta_objects_guard()}; thread_ = std::thread{f, detail::global_meta_objects_guard()};
} }
} }
......
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