如何欺骗的boost :: ASIO只允许布展处理器 [英] How to trick boost::asio to allow move-only handlers

查看:139
本文介绍了如何欺骗的boost :: ASIO只允许布展处理器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一个RPC通信协议,方法的调用后,我送完成的消息返回给调用者。由于方法是在并行的方式调用,需要包含响应(A 的std ::字符串)的缓冲由一个互斥锁保护。我想要实现的是以下内容:

In a RPC communication protocol, after the invocation of a method I'm sending "done" messages back to the caller. Since the methods are invoked in a concurrent fashion, the buffer containing the response (a std::string) needs to be protected by a mutex. What I'm trying to achieve is the following:

void connection::send_response()
{
    // block until previous response is sent
    std::unique_lock<std::mutex> locker(response_mutex_);

    // prepare response
    response_ = "foo";

    // send response back to caller. move the unique_lock into the binder
    // to keep the mutex locked until asio is done sending.
    asio::async_write(stream_,
                      asio::const_buffers_1(response_.data(), response_.size()),
                      std::bind(&connection::response_sent, shared_from_this(),
                                _1, _2, std::move(locker))
                      );
}

void connection::response_sent(const boost::system::error_code& err, std::size_t len)
{
    if (err) handle_error(err);
    // the mutex is unlocked when the binder is destroyed
}

不过,这不能编译,因为的boost :: ASIO 需要的处理程序可复制构造

这个问题可以通过使用下面的共享柜类,而不是 unique_lock 各地工作(尽管不是很优雅)

The problem can be worked around (albeit not very elegantly) by using the following shared locker class instead of unique_lock:

template <typename Mutex>
class shared_lock
{
public:
    shared_lock(Mutex& m)
    : p_(&m, std::mem_fn(&Mutex::unlock))
    { m.lock(); }

private:
    std::shared_ptr<Mutex> p_;
};

什么是落后的boost :: ASIO 不是只允许布展处理程序?

What is the reasoning behind boost::asio not allowing move-only handlers?

推荐答案

直到克里斯Kohlhoff响应我提出的错误,这里有一个简单的解决方法:

Until Chris Kohlhoff responds to the bug I've filed, here's a simple workaround:

template <typename F>
struct move_wrapper : F
{
    move_wrapper(F&& f) : F(std::move(f)) {}

    move_wrapper(move_wrapper&&) = default;
    move_wrapper& operator=(move_wrapper&&) = default;

    move_wrapper(const move_wrapper&);
    move_wrapper& operator=(const move_wrapper&);
};

template <typename T>
auto move_handler(T&& t) -> move_wrapper<typename std::decay<T>::type>
{
    return std::move(t);
}

该包装声明拷贝构造函数,欺骗ASIO机械就范,但从来没有定义它,这样复制会导致一个链接错误。

The wrapper declares a copy constructor, tricking asio's machinery into submission, but never defines it, so that copying would result in a linking error.

现在,人们终于可以做到这一点:

Now one can finally do this:

std::packaged_task<int()> pt([] {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return 42;
});
std::future<int> fu = pt.get_future();

boost::asio::io_service io;
io.post(move_handler(pt));
std::thread(&boost::asio::io_service::run, &io).detach();

int result = fu.get();
assert(result == 42);

这篇关于如何欺骗的boost :: ASIO只允许布展处理器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆