我可以在 C++ Actor Framework 中使用 C++11 智能指针作为消息返回类型吗?

Posted

技术标签:

【中文标题】我可以在 C++ Actor Framework 中使用 C++11 智能指针作为消息返回类型吗?【英文标题】:Can I use C++11 smart pointers as a message return type in the C++ Actor Framework? 【发布时间】:2015-11-10 21:44:21 【问题描述】:

当我使用 unique_ptr 作为返回类型时,我收到编译器错误 C2280:

'caf::detail::tuple_vals<std::unique_ptr<A,std::default_delete<_Ty>>>::tuple_vals(const caf::detail::tuple_vals<std::unique_ptr<_Ty,std::default_delete<_Ty>>> &)': attempting to reference a deleted function  include\caf\detail\tuple_vals.hpp   102

以下是一些说明问题的示例代码(根据 C++ Actor Framework 示例之一修改):

#include <iostream>
#include "caf/all.hpp"

using namespace caf;
using namespace std;

class A

public:
    int a;

    A(int a)
    
        this->a = a;
    
;

using a_type = typed_actor<replies_to<int>::with<unique_ptr<A>>>;

a_type::behavior_type a_behavior(a_type::pointer self)

    return
    
        [self](const int& a) -> unique_ptr<A>
        
            return make_unique<A>(5);
        
    ;


void tester(event_based_actor* self, const a_type& testee)

    self->link_to(testee);
    // will be invoked if we receive an unexpected response message
    self->on_sync_failure(
        [=]
        
            aout(self) << "AUT (actor under test) failed" << endl;
            self->quit(exit_reason::user_shutdown);
        );
    self->sync_send(testee, 5).then(
        [=](unique_ptr<A> a)
        
            if(a->a == 5)
            
                aout(self) << "AUT success" << endl;
            

            self->send_exit(testee, exit_reason::user_shutdown);
        
    );

【问题讨论】:

消息中的所有类型都必须是正则的,即具有值语义。运行时仅在 分离 消息时调用复制构造函数,这发生在尝试获取对引用计数大于 1 的消息值的非常量访问时。 @MatthiasVallentin 如果我明白你在说什么,那么我在下面的回答是不正确的(它恰好可以编译)。如果您将评论扩展到答案,我很乐意接受! 【参考方案1】:

CAF 要求消息中的每种类型都是常规。这意味着它必须提供一个复制构造函数,而std::unique_ptr 没有。因此编译器会抱怨。

消息具有写时复制实现。您可以廉价地复制一条消息,因为它只会在内部增加引用计数。您可以随时对消息元素执行 const 访问。仅当消息的引用计数大于 1 并且您请求非常量访问时,写入时复制的“写入”部分才会启动。此时,运行时调用所包含类型的复制构造函数来创建新消息。

如果 CAF 会无条件地执行此复制,而与引用计数无关,那么将无法有效地支持数据流编程,即参与者接收消息、修改其内容并转发到下一个阶段。

将消息视为指针容器:包含的元素在空闲存储中分配。在消息中存储指针通常是设计缺陷。双重包装也给分配器带来了不必要的压力。

由于您可以灵活地对消息进行切片,因此您无需创建单个消息,然后就可以在各种上下文中使用包含的值。

【讨论】:

【参考方案2】:

是的,C++ Actor Framework 确实允许在返回消息中使用智能指针,但不能采用 unique_ptr 的形式。

C++ Actor Framework 实现当前会复制消息并取消引用unique_ptr,从而导致编译器错误。

不要使用unique_ptr,而是使用shared_ptr。修改问题的示例代码时,引用计数将为 2。尽管创建了第二个share_ptr,但我还使用了自定义删除函数来验证内存是否按预期释放。

【讨论】:

以上是关于我可以在 C++ Actor Framework 中使用 C++11 智能指针作为消息返回类型吗?的主要内容,如果未能解决你的问题,请参考以下文章

CAF(C++ actor framework)使用随笔(unbecome与keep_behavior用法)

C++ Actor并发模型框架 Actor Framework (CAF)

CAF(C++ actor framework)使用随笔(使用类去构建actor和使用的一些思路)

CAF(C++ actor framework)(序列化之类,无需序列化,直接传)

CAF(C++ actor framework)使用随笔(各种send通信用法)

CAF(C++ actor framework)使用随笔(延迟发送,消息转发,消息优先级)