CAF:c++ actor framework

簡介

CAF 是 C++ Actor 模型框架,借鑑了 erlang 和 akka 的 actor 思想。有強 C++ 11 特性。 特點是:輕量級,分佈式,簡單,可適應以及無鎖。
官方文檔:https://actor-framework.readthedocs.io/en/latest/index.html
Github地址: https://github.com/actor-framework/actor-framework
wike地址: https://github.com/actor-framework/actor-framework/wiki

下載/編譯/安裝

下載

Linux – Git 下載方式
CAF GitHub 地址 : https://github.com/actor-framework/actor-framework
Git 下載 ,下載源碼 master :
備註:還需要安裝 boost

git clone https://github.com/actor-framework/actor-framework.git

下載所有的 模塊和 庫。

git clone --recursive https://github.com/actor-framework/actor-framework.git

編譯/安裝

在linux 系統下載好後。在當前目錄下,能看到 actor-framework 文件夾。
執行如下命令:

cd actor-framework #進入caf 文件夾
./configure #執行configure 腳本,配置對應屬性,按照默認屬性配置
make 	#編譯
make install #安裝命令
make uninstall #卸載命令,如需卸載,執行此命令就可以。

簡單使用

單次調用,沒有使用線程池

#include <iostream>
#include <string>
#include <caf/all.hpp>
#include <caf/io/all.hpp>

caf::behavior msgHandle(caf::event_based_actor *self)
{
    return{
        [=](std::string &what)
        {
            std::cout<<"string type msg is :"<<what<<std::endl;
        },
        [=](int &value)
        {
            std::cout<<"int type msg is:"<<value<<std::endl;
        }
    };   
}

int main()
{
    std::cout<<"main.cpp"<<std::endl;
    caf::actor_system_config cfg;
    caf::actor_system system(cfg);
    auto a1 = system.spawn(msgHandle);
    caf::anon_send(a1,"String 類型消息");
    caf::anon_send(a1,123456789);

    return 0;
}

編譯:

g++ -g main.cpp -lcaf_core -o main

輸出如下:

main.cpp
string type msg is :String 類型消息
int type msg is:123456789

複雜使用

主要針對 : event_based_actor 類型說明

思路

啓用線程操作,根據項目的實際需求使用,定義不同的消息註釋,用來接收處理。
增加了如下文件:msgHandle.cpp msgHandle.h

main.cpp 內容如下

#include <iostream>
#include <string>
#include <caf/all.hpp>
#include <caf/io/all.hpp>
#include <boost/shared_ptr.hpp>

#include "msgHandle.h"

int main()
{
    std::cout<<"main.cpp"<<std::endl;
    //spawn some actors
    caf::actor_system_config cfg;
    caf::actor_system system(cfg);
    //an actor executed in the current thread
    caf::scoped_actor self(system);
    
    msgHandelActor = boost::shared_ptr<caf::actor>(new caf::actor(self->spawn<caf::detached>(msgHandleFuntion)));

    ActorRun::instance()->startActorOne("output:startOne");
    ActorRun::instance()->startActorTwo("output:startTwo ",123);
    ActorRun::instance()->startActorDelay(false,5,"output: ",0);

    self->await_all_other_actors_done();
    system.await_all_actors_done();
    return 0;
}

msgHandle.h

· Atoms / 消息體智能指針 /behavior

//定義actor 智能指針 msgHandleActor
extern boost::shared_ptr<caf::actor> msgHandelActor;
//定義原子-消息註釋 actorOne,actorTwo,actorDelay 
// 注意消息內容長度小於11
using actorOne = caf::atom_constant<caf::atom("actorOne")>;
using actorTwo = caf::atom_constant<caf::atom("actorTwo")>;
using actorDelay = caf::atom_constant<caf::atom("catorDelay")>;
//函數聲明 msgHandleFuntion 
caf::behavior msgHandleFuntion(caf::event_based_actor *self);
  • 執行類 - 詳細註釋不做說明。
class ActorRun{
    public:
        ActorRun();
        ~ActorRun();
        static ActorRun* instance();
        void startActorOne(std::string what);
        void startActorTwo(std::string what,int value);
         /**
         * @brief startActorDelay  --延時發送處理函數
         * @param type      --延時類型 0:毫秒 1:秒 
         * @param step      --延時步長
         * @param what      --消息內容 -- string類型值
         * @param value     --消息內容 -- double類型值
         */
        void startActorDelay(bool type,int step,std::string what,double value);
    private:
    // 內部計數值。循環次數
    int _count;
};

msgHandle.cpp

  • 消息處理函數
caf::behavior msgHandleFuntion(caf::event_based_actor *self)
{
    return{
        [=](actorOne it,std::string &what)
        {
            std::cout<<"actorOne: "<<what<<std::endl;
        },
        [=](actorTwo it,std::string &what,int &value)
        {
            std::cout<<"actorTwo: "<<what<<"value:"<<value<<std::endl;
        },
        [=](actorDelay it,std::string &what,int &count,double &value)
        {
            std::cout<<"actorDelay: "<<"count:"<<count<<" text:"<< what<<" value:"<<value<<std::endl;
            ActorRun::instance()->startActorDelay(true,5,"output: ",1.11*(count+1));
        }
    };
}

atom 對應消息發送函數

void ActorRun::startActorOne(std::string what)
{
    caf::anon_send(*msgHandelActor,actorOne::value,what);
}

void ActorRun::startActorTwo(std::string what,int value)
{
    caf::anon_send(*msgHandelActor,actorTwo::value,what,value);
}

void ActorRun::startActorDelay(bool type,int step,std::string what,double value)
{
    if(_count == 10) return;
    if(!type) 
        caf::delayed_anon_send(*msgHandelActor,std::chrono::milliseconds(step),actorDelay::value,what,_count,value);
    else
        caf::delayed_anon_send(*msgHandelActor,std::chrono::seconds(step),actorDelay::value,what,_count,value);
    _count ++;
}
  • 編譯命令
g++ -g main.cpp msgHandle.cpp -lcaf_core -o main
  • 運行結果
main.cpp
actorOne: output:startOne
actorTwo: output:startTwo value:123
actorDelay: count:0 text:output:  value:0
actorDelay: count:1 text:output:  value:1.11
actorDelay: count:2 text:output:  value:2.22
actorDelay: count:3 text:output:  value:3.33
actorDelay: count:4 text:output:  value:4.44
actorDelay: count:5 text:output:  value:5.55
actorDelay: count:6 text:output:  value:6.66
actorDelay: count:7 text:output:  value:7.77
actorDelay: count:8 text:output:  value:8.88
actorDelay: count:9 text:output:  value:9.99

blocking_actor 類型說明

釋義

Blocking actors always run in a separate thread and are not scheduled by CAF. Unlike event-based actors, blocking actors have explicit, blocking receive functions. Further, blocking actors do not handle system messages automatically via special-purpose callbacks (see Default and System Message Handlers). This gives users full control over the behavior of blocking actors. However, blocking actors still should follow conventions of the actor system. For example, actors should unconditionally terminate after receiving an exit_msg with reason exit_reason::kill
具體翻譯不做說明,大概功能,類似與線程中,阻塞鎖,在生命週期內,一直處於活動狀態,直到滿足特定條件,退出。

函數說明

  • 接收函數
void blockingCalculatorFuntion(caf::blocking_actor *self)
{
    bool running = true;
    self->receive_while(running)
    (
        [](actorOne it,std::string &what)
        {
            std::cout<<"Block: -- "<<"actorOne: "<<what<<std::endl;
        },
        [](actorTwo it,std::string &what,int &value)
        {
            std::cout<<"Block: -- "<<"actorTwo: "<<what<<"value:"<<value<<std::endl;
        },
        //退出條件,直到接收到 actorLoop 原子消息,退出
        [&](actorLoop it,std::string &what)
        {
            std::cout<<"Block: -- "<<"Exit!"<<std::endl;
            running =false;
        }
    );
}
  • 消息指針定義,原子消息註釋定義
extern boost::shared_ptr<caf::actor> msgHandelLoopActor;
using actorLoop = caf::atom_constant<caf::atom("actorLoop")>;

消息發送函數

void ActorRun::startActorLoop_One()
{
    caf::anon_send(*msgHandelLoopActor,actorOne::value,"Running");
}
//退出函數
void ActorRun::startActorLoop()
{
    caf::anon_send(*msgHandelLoopActor,actorLoop::value,"Exit");
}
  • 消息指針 spwan
msgHandelLoopActor = boost::shared_ptr<caf::actor>(new caf::actor(self->spawn<caf::detached>(blockingCalculatorFuntion)));
  • 消息發送-- main函數內部
    ActorRun::instance()->startActorLoop_One();
    ActorRun::instance()->startActorLoop();
    ActorRun::instance()->startActorLoop_One();
  • 執行結果如下:
main.cpp
Block: -- actorOne: Running
Block: -- Exit!

blocking_actor ,在退出之後,結束生命週期,處於disable狀態,再次發送消息,不會響應。在生產環境中使用,看個人理解了。

其他loop 類型

主要有三種循環接收,receive_while, receive_for and do_receive。很直觀,while,for,do-while
官方樣例如下:
while

 size_t received = 0;
 receive_while([&] { return received < 10; }) (
   [&](int) {
     ++received;
   }
 );

for

 std::vector<int> results;
 size_t i = 0;
 receive_for(i, 10) (
   [&](int value) {
     results.push_back(value);
   }
 );

do-while

 size_t received = 0;
 do_receive (
   [&](int) {
     ++received;
   }
 ).until([&] { return received >= 10; });

使用哪種循環方式,根據個人需求來使用了。

其他說明

一些特性說明: https://blog.csdn.net/xzwdev/article/details/41700001
還有一些其他功能.日誌輸出I/O功能
一些相關特性:同步發送異步發送消息跳過沒有做相關說明,可以參考官方文檔。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章