ractor/actor/
actor_id.rs

1// Copyright (c) Sean Lawlor
2//
3// This source code is licensed under both the MIT license found in the
4// LICENSE-MIT file in the root directory of this source tree.
5
6//! This module handles everything around actor id's. In the event you have a
7//! remote actor, the actor's ID will denote not only the actor's instance id, but
8//! the id of the remote node the actor is running on.
9//!
10//! ActorIds are generally helpful in logging and pattern matching, but not directly
11//! used in addressing outside of `ractor_cluster` network-based call internals.
12
13use std::fmt::Display;
14use std::sync::atomic::AtomicU64;
15
16/// An actor's globally unique identifier
17#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
18pub enum ActorId {
19    /// A local pid
20    Local(u64),
21
22    /// A remote actor on another system (system, id)
23    Remote {
24        /// The remote node id
25        node_id: u64,
26        /// The local id on the remote system
27        pid: u64,
28    },
29}
30
31impl ActorId {
32    /// Determine if this actor id is a local or remote actor
33    ///
34    /// Returns [true] if it is a local actor, [false] otherwise
35    pub const fn is_local(&self) -> bool {
36        matches!(self, ActorId::Local(_))
37    }
38
39    /// Retrieve the actor's PID
40    ///
41    /// Returns the actor's [u64] instance identifier (process id).
42    pub const fn pid(&self) -> u64 {
43        match self {
44            ActorId::Local(pid) => *pid,
45            ActorId::Remote { pid, .. } => *pid,
46        }
47    }
48
49    /// Retrieve the node id of this PID. 0 = a local actor, while
50    /// any non-zero value is the ide of the remote node running this actor
51    pub const fn node(&self) -> u64 {
52        match self {
53            ActorId::Local(_) => 0,
54            ActorId::Remote { node_id, .. } => *node_id,
55        }
56    }
57}
58
59impl Display for ActorId {
60    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        match self {
62            ActorId::Local(id) => write!(f, "0.{id}"),
63            ActorId::Remote { node_id, pid } => write!(f, "{node_id}.{pid}"),
64        }
65    }
66}
67
68/// The local id allocator for actors
69static ACTOR_ID_ALLOCATOR: AtomicU64 = AtomicU64::new(0u64);
70
71/// Retrieve a new local id
72pub(crate) fn get_new_local_id() -> ActorId {
73    ActorId::Local(ACTOR_ID_ALLOCATOR.fetch_add(1, std::sync::atomic::Ordering::AcqRel))
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn test_pid() {
82        let actor_id = ActorId::Local(123);
83        assert_eq!(123, actor_id.pid());
84        let actor_id = ActorId::Remote {
85            node_id: 1,
86            pid: 123,
87        };
88        assert_eq!(123, actor_id.pid());
89    }
90
91    #[test]
92    fn test_is_local() {
93        let actor_id = ActorId::Local(123);
94        assert!(actor_id.is_local());
95        let actor_id = ActorId::Remote {
96            node_id: 1,
97            pid: 123,
98        };
99        assert!(!actor_id.is_local());
100    }
101}