diff --git a/include/thespian/handle.hpp b/include/thespian/handle.hpp index 80cdc98..477ab87 100644 --- a/include/thespian/handle.hpp +++ b/include/thespian/handle.hpp @@ -46,13 +46,9 @@ private: auto operator==(const handle &, const handle &) -> bool; -/// Stable opaque actor identity: the raw instance pointer. Two handles for -/// the same actor return the same value. Returns 0 for expired handles. -[[nodiscard]] inline auto instance_id(const handle &h) -> uintptr_t { - // NOLINTNEXTLINE(*-reinterpret-cast) - if (auto sp = handle_ref(h).lock()) - return reinterpret_cast(sp.get()); - return 0; -} +/// Stable numeric actor identity assigned at spawn (atomic incrementing +/// counter, starting at 1). Two handles for the same actor return the same +/// value. Returns 0 for a null or expired handle. +[[nodiscard]] auto instance_id(const handle &h) -> uintptr_t; } // namespace thespian diff --git a/src/instance.cpp b/src/instance.cpp index acfac01..01e23cc 100644 --- a/src/instance.cpp +++ b/src/instance.cpp @@ -85,6 +85,8 @@ using namespace std::chrono_literals; namespace thespian { +static atomic next_instance_id{1}; // NOLINT(*-avoid-non-const-global-variables) + struct context_impl : context { explicit context_impl(executor::context executor) : executor{move(executor)} {} @@ -226,6 +228,7 @@ struct instance : std::enable_shared_from_this { instance(context_impl &ctx, behaviour b, exit_handler eh, string_view name, env_t env) : ctx(ctx), strand_(ctx.executor.create_strand()), name_{name}, + instance_id_{next_instance_id.fetch_add(1, memory_order_relaxed)}, env_(move(env)) { if (eh) exit_handlers_.emplace_front(eh); @@ -491,6 +494,7 @@ struct instance : std::enable_shared_from_this { context_impl &ctx; executor::strand strand_; string name_; + uintptr_t instance_id_; receiver receiver_; receiver exited_receiver_; sync_receiver sync_receiver_; @@ -596,6 +600,12 @@ auto context::spawn_link(behaviour b, exit_handler eh, string_view name) return spawn_link(move(b), move(eh), name, env_t{}); } +auto instance_id(const handle &h) -> uintptr_t { + if (auto sp = handle_ref(h).lock()) + return sp->instance_id_; + return 0; +} + auto env() -> env_t & { return private_call().env_; } auto self() -> handle { return make_handle(private_call().lifetime_); } auto self_ref() -> handle & { return private_call().self_ref_; }