[xactor]學習筆記--2--addr

打雜的我,又閑下來有時間繼續(xù)看代碼了蹭睡。
人狠話不多衍菱,上代碼。我們先看actor肩豁。
actor.rs 前面部分引用的東西

use crate::addr::ActorEvent;
use crate::runtime::spawn;
use crate::{Addr, Context};
use futures::channel::mpsc::UnboundedReceiver;
use futures::channel::oneshot;
use futures::lock::Mutex;
use futures::{FutureExt, StreamExt};
use std::sync::Arc;
use anyhow::Result;

這個時候看到第一個addr:ActorEvent.

type ExecFuture = Pin<Box<dyn Future<Output = ()> + Send + 'static>>;

pub(crate) type ExecFn<A> =
    Box<dyn FnOnce(Arc<Mutex<A>>, Arc<Context<A>>) -> ExecFuture + Send + 'static>;

pub(crate) enum ActorEvent<A> {
    Exec(ExecFn<A>),
    Stop(Option<Error>),
}

我們看到
ExecFuture 是定義了一個Type脊串, 把Future 放到一個Box里面 ,再放到Pin中清钥。
ExecFn 是定義了一個 執(zhí)行函數的類型
ActorEvent 是枚舉 Actor的事件有哪些琼锋。

接著還有use crate::{Addr, Context};
Actor模型定義來說,Addr對應的就是mailbox.
我們看下定義

pub struct Addr<A> {
    pub(crate) actor_id: u64,
    pub(crate) tx: mpsc::UnboundedSender<ActorEvent<A>>,
    pub(crate) rx_exit: Option<Shared<oneshot::Receiver<()>>>,
}

核心的東西來了 祟昭,他來了缕坎。
actor_id 是定義了id,是u64
tx 是發(fā)送通道, , 用的是std的 mpsc,發(fā)送的內容是Actor的事件篡悟。
rx_exit 是定義接收通道谜叹,用的是oneshot::Receiver.

接著我們就轉到先看addr.rs

//這些代碼主要是完成Addr的Clone,PartialEq ,Hash 

impl<A> Clone for Addr<A> {
    fn clone(&self) -> Self {
        Self {
            actor_id: self.actor_id,
            tx: self.tx.clone(),
            rx_exit: self.rx_exit.clone(),
        }
    }
}

// 
impl<A> PartialEq for Addr<A> {
    fn eq(&self, other: &Self) -> bool {
        self.actor_id == other.actor_id
    }
}

impl<A> Hash for Addr<A> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.actor_id.hash(state)
    }
}

完成對Addr的主要接口實現
impl<A: Actor> Addr<A> {
    /// Returns the id of the actor.
  //返回actor的ID
    pub fn actor_id(&self) -> u64 {
        self.actor_id
    }

    /// Stop the actor. 停止actor.通過發(fā)送事件恰力,進行停止
    pub fn stop(&mut self, err: Option<Error>) -> Result<()> {
        self.tx.start_send(ActorEvent::Stop(err))?;
        Ok(())
    }

    /// Send a message `msg` to the actor and wait for the return value.
  ///  發(fā)送一個消息給actor 并且等待返回值
    pub async fn call<T: Message>(&mut self, msg: T) -> Result<T::Result>
    where
        A: Handler<T>,
    {
        let (tx, rx) = oneshot::channel();
        self.tx
            .start_send(ActorEvent::Exec(Box::new(move |actor, ctx| {
                Box::pin(async move {
                    let mut actor = actor.lock().await;
                    let res = Handler::handle(&mut *actor, &ctx, msg).await;
                    let _ = tx.send(res);
                })
            })))?;

        Ok(rx.await?)
    }

    /// Send a message `msg` to the actor without waiting for the return value.
    // 發(fā)送一個消息給actor 不等待返回值
    pub fn send<T: Message<Result = ()>>(&mut self, msg: T) -> Result<()>
    where
        A: Handler<T>,
    {
        self.tx
            .start_send(ActorEvent::Exec(Box::new(move |actor, ctx| {
                Box::pin(async move {
                    let mut actor = actor.lock().await;
                    Handler::handle(&mut *actor, &ctx, msg).await;
                })
            })))?;
        Ok(())
    }

    /// Create a `Caller<T>` for a specific message type
   /// 為特定的消息類型創(chuàng)建一個“Caller”
    pub fn caller<T: Message>(&self) -> Caller<T>
    where
        A: Handler<T>,
    {
        let addr = self.clone();
        Caller(Box::new(move |msg| {
            let mut addr = addr.clone();
            Box::pin(async move { addr.call(msg).await })
        }))
    }

    /// Create a `Sender<T>` for a specific message type
  /// 為特定的消息類型創(chuàng)建一個“Sender”
    pub fn sender<T: Message<Result = ()>>(&self) -> Sender<T>
    where
        A: Handler<T>,
    {
        let addr = self.clone();
        Sender(Box::new(move |msg| {
            let mut addr = addr.clone();
            addr.send(msg)
        }))
    }

    /// Wait for an actor to finish, and if the actor has finished, the function returns immediately.
  ///等待actor 完成叉谜,如果actor 已經完成旗吁,函數立即返回踩萎。
    pub async fn wait_for_stop(self) {
        if let Some(rx_exit) = self.rx_exit {
            rx_exit.await.ok();
        } else {
            futures::future::pending::<()>().await;
        }
    }
}

首先我們先看第一個

pub async fn call<T: Message>(&mut self, msg: T) -> Result<T::Result>
    where
        A: Handler<T>,

代碼中我們又看到使用了Message,Handler的類型很钓。
繼續(xù)翻找香府;

/// Represents a message that can be handled by the actor.
///表示可以由 actor 處理的消息董栽。
pub trait Message: 'static + Send {
    /// The return value type of the message
    /// This type can be set to () if the message does not return a value, or if it is a notification message
    type Result: 'static + Send;
}

/// Describes how to handle messages of a specific type.描述如何處理特定類型的消息。
/// Implementing Handler is a general way to handle incoming messages.實現Handler是處理傳入消息的一種常用方法企孩。
/// The type T is a message which can be handled by the actor.類型T是可以由actor處理的消息锭碳。
#[async_trait::async_trait]
pub trait Handler<T: Message>: Actor {
    /// Method is called for every message received by this Actor.
    async fn handle(&mut self, ctx: &Context<Self>, msg: T) -> T::Result;
}

然后我們繼續(xù)看下一個。

pub fn caller<T: Message>(&self) -> Caller<T>
    where
        A: Handler<T>,

有一個新的類型 Caller

use crate::{Message, Result};
use std::future::Future;
use std::pin::Pin;

pub(crate) type CallerFn<T> = Box<
    dyn Fn(T) -> Pin<Box<dyn Future<Output = Result<<T as Message>::Result>> + Send + 'static>>
        + 'static,
>;

pub(crate) type SenderFn<T> = Box<dyn Fn(T) -> Result<()> + 'static + Send>;

/// Caller of a specific message type
pub struct Caller<T: Message>(pub(crate) CallerFn<T>);

impl<T: Message> Caller<T> {
    pub async fn call(&mut self, msg: T) -> Result<T::Result> {
        self.0(msg).await
    }
}

/// Sender of a specific message type
pub struct Sender<T: Message>(pub(crate) SenderFn<T>);

impl<T: Message<Result = ()>> Sender<T> {
    pub fn send(&mut self, msg: T) -> Result<()> {
        self.0(msg)
    }
}

其中我們三個文件都看到了一個引用

use crate:: Result;

我們在lib.rs 中看到定義

/// Alias of anyhow::Result
pub type Result<T> = anyhow::Result<T>;

/// Alias of anyhow::Error
pub type Error = anyhow::Error;

看到actor的Result 和Error都是使用 anyhow勿璃。

從代碼上我們知道擒抛,actor 的 addr 具有的屬性和函數。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末补疑,一起剝皮案震驚了整個濱河市歧沪,隨后出現的幾起案子,更是在濱河造成了極大的恐慌莲组,老刑警劉巖诊胞,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異锹杈,居然都是意外死亡撵孤,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門竭望,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邪码,“玉大人,你說我怎么就攤上這事咬清∠佳铮” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵枫振,是天一觀的道長喻圃。 經常有香客問我,道長粪滤,這世上最難降的妖魔是什么斧拍? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮杖小,結果婚禮上肆汹,老公的妹妹穿的比我還像新娘。我一直安慰自己予权,他們只是感情好昂勉,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著扫腺,像睡著了一般岗照。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天攒至,我揣著相機與錄音厚者,去河邊找鬼。 笑死迫吐,一個胖子當著我的面吹牛库菲,可吹牛的內容都是我干的。 我是一名探鬼主播志膀,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼熙宇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了溉浙?” 一聲冷哼從身側響起奇颠,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎放航,沒想到半個月后烈拒,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡广鳍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年荆几,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赊时。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡吨铸,死狀恐怖,靈堂內的尸體忽然破棺而出祖秒,到底是詐尸還是另有隱情诞吱,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布竭缝,位于F島的核電站房维,受9級特大地震影響,放射性物質發(fā)生泄漏抬纸。R本人自食惡果不足惜咙俩,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望湿故。 院中可真熱鬧阿趁,春花似錦、人聲如沸坛猪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽墅茉。三九已至命黔,卻和暖如春呜呐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纷铣。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留战转,地道東北人搜立。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像槐秧,于是被迫代替她去往敵國和親啄踊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344