|
1 | 1 | # Typed References
|
| 2 | + |
| 3 | +Typed references are strongly typed wrappers over raw identifiers like `ActorId` and `PortId`. These types are used throughout hyperactor’s APIs; as parameters in messages, return values from `bind()` methods, and elements in routing decisions. They make distributed communication safe, expressive, and statically checked. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +There are three main typed reference types: |
| 8 | + |
| 9 | +- [`ActorRef<A>`](#actorrefa): A typed reference to an actor implementing the `RemoteActor` trait. |
| 10 | +- [`PortRef<M>`](#portrefm): A reference to a reusable mailbox port for messages of type `M`. |
| 11 | +- [`OncePortRef<M>`](#onceportrefm): A reference to a one-shot port for receiving a single response of type `M`. |
| 12 | + |
| 13 | +These types are used as parameters in messages, return values from bindings, and components of the routing system. |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +## `ActorRef<A>` |
| 18 | + |
| 19 | +`ActorRef<A>` is a typed reference to an actor of type `A`. It provides a way to identify and address remote actors that implement `RemoteActor`. |
| 20 | + |
| 21 | +```rust |
| 22 | +let actor_ref: ActorRef<MyActor> = ActorRef::attest(actor_id); |
| 23 | +``` |
| 24 | + |
| 25 | +Unlike `ActorHandle<A>`, an `ActorRef` is just a reference — it doesn’t guarantee that the actor is currently running. It's primarily used for routing and type-safe messaging across `Proc`s. |
| 26 | + |
| 27 | +### Definition |
| 28 | +```rust |
| 29 | +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] |
| 30 | +pub struct ActorRef<A: RemoteActor> { |
| 31 | + actor_id: ActorId, |
| 32 | + phantom: PhantomData<A>, |
| 33 | +} |
| 34 | +``` |
| 35 | +This type is a thin wrapper around an `ActorId`, with a phantom type `A` to track which actor it refers to. It ensures you can only send messages supported by the actor's declared `RemoteHandles`. |
| 36 | + |
| 37 | +## `PortRef<M>` |
| 38 | + |
| 39 | +`PortRef<M>` refers to a mailbox port for messages of type `M`. |
| 40 | +```rust |
| 41 | +let (port, mut receiver) = actor.open_port::<MyMessage>(); |
| 42 | +let port_ref: PortRef<MyMessage> = port.bind(); |
| 43 | +``` |
| 44 | + |
| 45 | +This allows the port to be sent across the network or passed into other messages. On the receiving end, `PortRef` can be used to deliver messages of the expected type. |
| 46 | + |
| 47 | +### Definition |
| 48 | + |
| 49 | +```rust |
| 50 | +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] |
| 51 | +pub struct PortRef<M: Message> { |
| 52 | + port_id: PortId, |
| 53 | + phantom: PhantomData<M>, |
| 54 | +} |
| 55 | +``` |
| 56 | +As with `ActorRef`, this is a typed wrapper around a raw identifier (`PortId`), carrying a phantom type for safety. It ensures that only messages of type `M` can be sent through this reference. |
| 57 | + |
| 58 | +## `OncePortRef<M>` |
| 59 | + |
| 60 | +A `OncePortRef<M>` is like a `PortRef`, but designed for exactly one response. Once used, it cannot be reused or cloned. |
| 61 | +```rust |
| 62 | +let (once_port, receiver) = actor.open_once_port::<MyMessage>(); |
| 63 | +let once_ref = once_port.bind(); |
| 64 | +``` |
| 65 | +These are commonly used for request/response interactions, where a single reply is expected. |
| 66 | + |
| 67 | +### Definition |
| 68 | + |
| 69 | +```rust |
| 70 | +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] |
| 71 | +pub struct OncePortRef<M: Message> { |
| 72 | + port_id: PortId, |
| 73 | + phantom: PhantomData<M>, |
| 74 | +} |
| 75 | +``` |
| 76 | +Just like `PortRef`, this wraps a `PortId` with a phantom message type `M` for type safety. Internally, the system enforces one-time delivery semantics, ensuring the port is closed after receiving a single message. |
| 77 | + |
| 78 | +## `GangRef<A>` |
| 79 | + |
| 80 | +A `GangRef<A>` is a typed reference to a gang of actors, all of which implement the same `RemoteActor` type `A`. |
| 81 | +```rust |
| 82 | +let gang_ref: GangRef<MyActor> = GangId::new(...).into(); |
| 83 | +``` |
| 84 | +You can extract an `ActorRef<A>` for a specific rank in the gang: |
| 85 | +```rust |
| 86 | +let actor = gang_ref.rank(0); // ActorRef<MyActor> |
| 87 | +``` |
| 88 | +This allows you to route messages to specific members of a replicated actor group, or to iterate over the gang for broadcasting, synchronization, or indexing. |
| 89 | + |
| 90 | +### Definition |
| 91 | +```rust |
| 92 | +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Hash, Ord)] |
| 93 | +pub struct GangRef<A: RemoteActor> { |
| 94 | + gang_id: GangId, |
| 95 | + phantom: PhantomData<A>, |
| 96 | +} |
| 97 | +``` |
| 98 | + |
| 99 | +#### Methods |
| 100 | +- `gang_ref.rank(rank: usize) -> ActorRef<A>` |
| 101 | +Returns a typed actor reference for the actor at the given rank in the gang. The method doesn’t validate the rank, so correctness is up to the caller. |
| 102 | +- `gang_ref.gang_id() -> &GangId` |
| 103 | +Returns the underlying, untyped gang identifier. |
0 commit comments