Theron应用层面的几个陌生概念

Theron 是一个用于并发编程的 C++ 库(http://www.theron-library.com/),通过 Theron 我们可以避免多线程开发中各种痛处,例如:共享内存、线程同步。Theron 通过 Actor 模型向我们展示了另一种思维。

本文不是Theron的入门理解教程,而是重点理解Theron三个方面的概念,包括Unhandled messages,Message registration,以及remote actor,分别对应翻译为:未处理消息,消息注册,以及分布式actor

Unhandled Messages

一个actor可以注册任意多个消息处理函数(handler),各个函数可以用来接收并处理不同类型的消息。如果当前接收到的消息类型,没有任何handler能够处理,那怎么办?默认情况下,消息将不会被处理,而是由回滚处理函数(fallback handler)发出一个错误。这种做法是为了帮助捕捉所谓的unhandled message。

我们能够重载actor对unhandled message的默认处理函数,取而代之的是用户自定义的一个特殊的默认消息处理函数(special default message handler)。一旦该处理函数在actor中被注册了,默认的handler将能够处理任何之前actor无法识别的消息类型,如下代码所示:

// A simple actor that prints out strings it receives. 
class Printer : public Theron::Actor 
{ 
public: 

    Printer(Theron::Framework &framework) : Theron::Actor(framework) 
    { 
        // Register the handler for string messages. 
        RegisterHandler(this, &Printer::Print); 

        // Register the default handler for all other kinds of messages. 
        // If we don't register our own default handler then the 'default' default 
        // handler will be used, which asserts on receiving an unhandled message. 
        SetDefaultHandler(this, &Printer::DefaultHandler); 
    } 

private: 

    void Print(const std::string &message, const Theron::Address from) 
    { 
        printf("%s\\n", message.c_str()); 

        // Send the message back for synchronization. 
        Send(message, from); 
    } 

    // Default handler which handles messages of unrecognized types. 
    // This is a 'blind' handler which takes the unhandled message as raw data. 
    void DefaultHandler( 
        const void *const data, 
        const Theron::uint32_t size, 
        const Theron::Address from) 
    { 
        DumpMessage(data, size, from); 
    } 
}; 

其中,默认的消息处理函数的主要问题是,在定义上,它们是无法知道它们要处理的消息的类型的。在此例中,我们采用了一种 blind handler的方式处理这些未知的消息类型,能够得到指向数据的指针和该数据类型的大小。此例中调用的DumpMessage()实现了将消息的内容导出的一个功能:

static void DumpMessage( 
    const void *const data, 
    const Theron::uint32_t size, 
    const Theron::Address from) 
{ 
    printf("Unhandled %d byte message sent from address %d:\n", 
        size, 
        from.AsInteger()); 

    // Dump the message as hex data. 
    if (data) 
    { 
        const char *const format("[%d] 0x%08x\n"); 

        const unsigned int *const begin(reinterpret_cast<const unsigned int *>(data)); 
        const unsigned int *const end(begin + size / sizeof(unsigned int)); 

        for (const unsigned int *word(begin); word != end; ++word) 
        { 
            printf(format, static_cast<int>(word - begin), *word); 
        } 
    } 
} 

尽管默认的消息处理函数很有用,但是每次都需要在actor中定义并注册。因此,这种处理函数一般用于特殊的actor(special actor)中,并不会用在所有的actor。

在框架层次存在一种类似于该特殊消息处理函数的机制,我们称之为fallback handlers。每个框架实例都注册了单个fallback handler,和actor默认的handler完全一样,但是只在以下两种情况:1)当消息发送至一个没有actor注册过的地址时;2)当消息发送给一个actor但是没有被该actor接收时,处理消息的时候直接执行一次回滚操作。

为了定义一个fallback handler,我们需要编写一个handler类,使得该handler的实例对象具备fallback handler,而且能够作为记录失败消息(log failed message)的地方。


// A handler object that reports any undelivered or unhandled messages. 
class FallbackHandler 
{ 
public: 

    // Fallback handler which handles any messages not handled by an actor. 
    // This is a 'blind' handler which takes the unhandled message as raw data. 
    void Handle( 
        const void *const data, 
        const Theron::uint32_t size, 
        const Theron::Address from) 
    { 
        DumpMessage(data, size, from); 
    } 
}; 

这里有一个主程序例子显示了同时使用默认消息处理函数和fallback handler的情况:

int main() 
{ 
    Theron::Receiver receiver; 
    Theron::Address printerAddress; 

    // Create a framework and register a fallback handler with it. 
    Theron::Framework framework; 
    FallbackHandler fallbackHandler; 
    framework.SetFallbackHandler(&fallbackHandler, &FallbackHandler::Handle); 

    { 
        // Create a printer actor within a local scope and remember its address. 
        Printer printer(framework); 
        printerAddress = printer.GetAddress(); 

        // Send the printer a message of a type which it doesn't handle. 
        // This message reaches the printer but is handled by its default handler. 
        framework.Send(103, receiver.GetAddress(), printerAddress); 

        // Send the printer a string message to show that it actually works. 
        framework.Send(std::string("hit"), receiver.GetAddress(), printerAddress); 

        // Wait for the reply to the handled string message, for synchronization. 
        receiver.Wait(); 
    } 

    // Send a string message to the printer's address, which is now stale. 
    // This message never reaches an actor so is handled by the fallback handler. 
    framework.Send(std::string("miss"), receiver.GetAddress(), printerAddress); 
} 

在这个例子中,我们创建了一个printer actor,并在主程序的最后,销毁了该actor。这种方式导致最后发送的消息去了一个未知的地址空间,因此违反了前面的第(1)中情况,此时消息将会被fallback handler处理。而第一次发送的消息的类型是被printer actor的default handler接受处理的。

Message registration

Theron中允许注册消息类型,注册的函数和头文件如下所示:

#include <Theron/Register.h> 

THERON_REGISTER_MESSAGE(std::string); 

对于单节点应用来说,注册消息类型完全是可选的。但是对于remote actor(用于分布式应用的actor)来说,必须在每个actor定义的地方注册消息的类型,可以是系统默认支持的消息类型,如string,也可以是自定义的消息类型,如某种类型的数据结构。

对于Remote actor和Message Registration的理解,可以通过我的另外一篇译文做更深入的了解。

原文地址:

unhandle message

message register

 

 

 

 

转载于:https://my.oschina.net/wanborj/blog/854551

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值