Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use C++11 smart pointers as a message return type in the C++ Actor Framework?

When I use a unique_ptr as the return type, I receive compiler error 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

Here's some example code that illustrates the issue (modified from one of the C++ Actor Framework examples):

#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);
        }
    );
}
like image 598
Stephen Rudolph Avatar asked Nov 10 '15 21:11

Stephen Rudolph


People also ask

Does C ++ 11 have smart pointers?

Introduction of Smart PointersC++11 comes up with its own mechanism that's Smart Pointer. When the object is destroyed it frees the memory as well. So, we don't need to delete it as Smart Pointer does will handle it.

What is smart pointer in C ++ 11?

Concept of the C++11 Smart Pointers Smart pointers are class objects that behave like built-in pointers but also manage objects that you create with new so that you don't have to worry about when and whether to delete them - the smart pointers automatically delete the managed object for you at the appropriate time.

Should I use unique_ptr or shared_ptr?

Use unique_ptr when you want to have single ownership(Exclusive) of the resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. A shared_ptr is a container for raw pointers.

What is smart pointer when should we use it asked me to implement unique_ptr of my own?

A smart pointer by comparison defines a policy as to when the object is destroyed. You still have to create the object, but you no longer have to worry about destroying it. The simplest policy in use involves the scope of the smart pointer wrapper object, such as implemented by boost::scoped_ptr or std::unique_ptr .


1 Answers

CAF requires that each type in a message is regular. This implies that it must provide a copy constructor, which std::unique_ptr doesn't have. Therefore the compiler complains.

Messages have a copy-on-write implementation. You can cheaply copy a single message, as it just bumps the reference count internally. At any time, you can perform const-access of the message elements. The "write" part of copy-on-write only kicks in if the reference count of a message is greater than 1 and you request non-const access. At that point the runtime invokes the copy constructor of the contained type to create a new message.

If CAF would unconditionally perform this copy, independent of the reference count, then it would not be possible to efficiently support data flow programming, where an actor receives a message, modifies its contents, and forwards on to the next stage.

Think of messages as pointer containers: the contained elements are allocated on the free store. Storing a pointer in a message is usually a design flaw. The double-wrapping also stresses the allocator unnecessarily.

Since you can slice messages flexibly, you get away with creating a single message and can then use the contained value in various contexts.

like image 140
mavam Avatar answered Sep 20 '22 05:09

mavam