Schauspieler -Rahmen für Rost
Any ) Um actix zu verwenden, fügen Sie dies Ihrer Cargo.toml :
[ dependencies ]
actix = " 0.13 " Um Actix zu verwenden, müssen Sie zunächst ein System erstellen.
fn main ( ) {
let system = actix :: System :: new ( ) ;
system . run ( ) ;
} Actix verwendet die Tokio -Laufzeit. System::new() erstellt eine neue Ereignisschleife. System.run() startet die Tokio -Ereignisschleife und wird fertig sein, sobald der System die SystemExit -Nachricht empfängt.
Um einen Akteur zu definieren, müssen Sie eine Struktur definieren und das Actor implementieren lassen.
use actix :: { Actor , Context , System } ;
struct MyActor ;
impl Actor for MyActor {
type Context = Context < Self > ;
fn started ( & mut self , _ctx : & mut Self :: Context ) {
println ! ( "I am alive!" ) ;
System :: current ( ) . stop ( ) ; // <- stop system
}
}
fn main ( ) {
let system = System :: new ( ) ;
let _addr = system . block_on ( async { MyActor . start ( ) } ) ;
system . run ( ) . unwrap ( ) ;
} Das Laichen eines neuen Schauspielers wird über den start und create Methoden des Akteursmerkmals. Es bietet verschiedene Möglichkeiten zur Schaffung von Schauspielern; Weitere Informationen finden Sie in den Dokumenten. Sie können die started implementieren, die Methoden des Akteursmerkmals stopping und stopped . started wird angerufen, wenn der Schauspieler beginnt und stopping wenn der Schauspieler fertig ist. Weitere Informationen zum Akteurlebenszyklus finden Sie in den API -Dokumenten.
Ein Schauspieler kommuniziert mit einem anderen Schauspieler, indem er Nachrichten sendet. In Actix werden alle Nachrichten eingegeben. Definieren wir eine einfache Sum mit zwei usize -Parametern und einem Schauspieler, der diese Nachricht akzeptiert und die Summe dieser beiden Zahlen zurückgibt. Hier verwenden wir das Attribut #[actix::main] als einfachere Möglichkeit, unser System zu starten und unsere Hauptfunktion .await fördern, damit wir leicht für die vom Actor zurückgesandten Antworten.
use actix :: prelude :: * ;
// this is our Message
// we have to define the response type (rtype)
# [ derive ( Message ) ]
# [ rtype ( usize ) ]
struct Sum ( usize , usize ) ;
// Actor definition
struct Calculator ;
impl Actor for Calculator {
type Context = Context < Self > ;
}
// now we need to implement `Handler` on `Calculator` for the `Sum` message.
impl Handler < Sum > for Calculator {
type Result = usize ; // <- Message response type
fn handle ( & mut self , msg : Sum , _ctx : & mut Context < Self > ) -> Self :: Result {
msg . 0 + msg . 1
}
}
# [ actix :: main ] // <- starts the system and block until future resolves
async fn main ( ) {
let addr = Calculator . start ( ) ;
let res = addr . send ( Sum ( 10 , 5 ) ) . await ; // <- send message and get future for result
match res {
Ok ( result ) => println ! ( "SUM: {}" , result ) ,
_ => println ! ( "Communication to the actor has failed" ) ,
}
} Alle Kommunikation mit Akteuren durchlaufen ein Addr -Objekt. Sie können eine Nachricht do_send ohne auf eine Antwort zu warten, oder Sie können einem Schauspieler eine bestimmte Nachricht send . Das Message definiert den Ergebnistyp für eine Nachricht.
Möglicherweise haben Sie festgestellt, dass die Methoden der Actor und Handler -Merkmale &mut self akzeptieren, und Sie können also gerne etwas in einem Schauspieler aufbewahren und es bei Bedarf mutieren.
Adressobjekte erfordern einen Schauspieler -Typ. Wenn wir jedoch nur eine bestimmte Nachricht an einen Akteur senden möchten, der die Nachricht verarbeiten kann, können wir die Recipient verwenden. Lassen Sie uns einen neuen Schauspieler erstellen, der Recipient verwendet.
use actix :: prelude :: * ;
use std :: time :: Duration ;
# [ derive ( Message ) ]
# [ rtype ( result = "()" ) ]
struct Ping {
pub id : usize ,
}
// Actor definition
struct Game {
counter : usize ,
name : String ,
recipient : Recipient < Ping > ,
}
impl Actor for Game {
type Context = Context < Game > ;
}
// simple message handler for Ping message
impl Handler < Ping > for Game {
type Result = ( ) ;
fn handle ( & mut self , msg : Ping , ctx : & mut Context < Self > ) {
self . counter += 1 ;
if self . counter > 10 {
System :: current ( ) . stop ( ) ;
} else {
println ! ( "[{0}] Ping received {1}" , self . name , msg . id ) ;
// wait 100 nanoseconds
ctx . run_later ( Duration :: new ( 0 , 100 ) , move |act , _| {
act . recipient . do_send ( Ping { id : msg . id + 1 } ) ;
} ) ;
}
}
}
fn main ( ) {
let system = System :: new ( ) ;
system . block_on ( async {
// To create a cyclic game link, we need to use a different constructor
// method to get access to its recipient before it starts.
let _game = Game :: create ( |ctx| {
// now we can get an address of the first actor and create the second actor
let addr = ctx . address ( ) ;
let addr2 = Game {
counter : 0 ,
name : String :: from ( "Game 2" ) ,
recipient : addr . recipient ( ) ,
}
. start ( ) ;
// let's start pings
addr2 . do_send ( Ping { id : 10 } ) ;
// now we can finally create first actor
Game {
counter : 0 ,
name : String :: from ( "Game 1" ) ,
recipient : addr2 . recipient ( ) ,
}
} ) ;
} ) ;
// let the actors all run until they've shut themselves down
system . run ( ) . unwrap ( ) ;
}Sehen Sie sich dieses Chat -Beispiel an, das umfassendere Nutzung in einem Netzwerk -Client/Server -Dienst zeigt.
Alle Beiträge sind willkommen. Wenn Sie eine Feature -Anfrage haben, zögern Sie nicht, ein Problem zu eröffnen!
Dieses Projekt ist unter einem von lizenziert
nach Ihrer Option.
Der Beitrag zum ACTIX -Repo ist nach den Bedingungen des Mitwirkenden Covenant organisiert. Das Actix -Team verspricht, einzugreifen, um diesen Verhaltenskodex aufrechtzuerhalten.