1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! Manage the lifecycle of an actix actor with its address.
//!
//! If you want to stop/terminate an actor, you call [`ActorContext::stop`](actix::ActorContext::stop) or
//! [`ActorContext::terminate`](actix::ActorContext::terminate) within its execution context.
//!
//! However, sometimes you have access to its address only. This crate adds a bunch of methods to the address so that
//! you may [stop](AddrSignalExt::stop) or [terminate](AddrSignalExt::terminate) the actor outside its running context.
//!
//! *Minimum supported rust version: 1.50.0*
//!
//! # Example
//!
//! ```
//! use actix::{Actor, Context};
//! use actix_signal::{AddrSignalExt, SignalHandler};
//! # use actix_signal_derive::SignalHandler;
//!
//! #[derive(SignalHandler)]
//! struct MyActor;
//!
//! impl Actor for MyActor {
//!     type Context = Context<Self>;
//! }
//!
//! # #[actix_rt::test]
//! # async fn test() {
//! let actor = MyActor;
//! let addr = actor.start();
//!
//! addr.stop();        // Stop the actor
//! addr.terminate();   // Terminate the actor
//! # }
//! ```
//!
//! You may also implement handlers by hand if you don't want to use the proc macro or need custom behaviors.
//!
//! ```
//! use actix::{Actor, Context, Handler, ActorContext};
//! use actix_signal::{AddrSignalExt, StopSignal, TerminateSignal};
//!
//! struct MyActor;
//!
//! impl Actor for MyActor {
//!     type Context = Context<Self>;
//! }
//!
//! impl Handler<StopSignal> for MyActor {
//!     type Result = ();
//!
//!     fn handle(&mut self, _msg: StopSignal, ctx: &mut Self::Context) -> Self::Result {
//!         ctx.stop();
//!     }
//! }
//!
//! impl Handler<TerminateSignal> for MyActor {
//!     type Result = ();
//!
//!     fn handle(&mut self, _msg: TerminateSignal, ctx: &mut Self::Context) -> Self::Result {
//!         ctx.terminate();
//!     }
//! }
//!
//! # #[actix_rt::test]
//! # async fn test() {
//! let actor = MyActor;
//! let addr = actor.start();
//!
//! addr.stop();        // Stop the actor
//! addr.terminate();   // Terminate the actor
//! # }
//! ```
//!
//! # Feature flags
//!
//! `derive` - Provide `#[derive(SignalHandler)]` proc-macro.

#[cfg(feature = "actix-signal-derive")]
#[macro_use]
extern crate actix_signal_derive;

use actix::dev::ToEnvelope;
use actix::{Actor, Handler};

#[cfg(feature = "actix-signal-derive")]
pub use actix_signal_derive::*;
pub use addr::*;
pub use signals::*;

mod addr;
mod private;
pub mod signals;

/// Actors that are able to handle signals.
///
/// This trait is sealed and automatically implemented for actors implementing `Handler`s for [`signals`](signals).
/// See top-level document for instructions on implementing these traits.
pub trait SignalHandler: Handler<StopSignal> + Handler<TerminateSignal> + private::Sealed {}

impl<T> SignalHandler for T where T: Handler<StopSignal> + Handler<TerminateSignal> {}

/// Execution contexts that are able to handle signals.
///
/// This trait is sealed and automatically implemented for contexts of which the associated actors implement `Handler`s
/// for [`signals`](signals).
/// See top-level document for instructions on implementing these traits.
pub trait ToSignalEnvelope<A>:
    ToEnvelope<A, StopSignal> + ToEnvelope<A, TerminateSignal> + private::Sealed
where
    A: Actor + SignalHandler,
    <A as Actor>::Context: ToSignalEnvelope<A>,
{
}

impl<A, T> ToSignalEnvelope<A> for T
where
    A: Actor<Context = T> + SignalHandler,
    T: ToEnvelope<A, StopSignal> + ToEnvelope<A, TerminateSignal>,
    <A as Actor>::Context: ToEnvelope<A, StopSignal> + ToEnvelope<A, TerminateSignal>,
{
}