回调和`std :: recursive_mutex`-有效的用例?

时间:2019-02-01 12:53:27

标签: c++ multithreading c++11 mutex recursive-mutex

我具有以下多态接口:

struct service
{
    virtual void connect(std::function<void>(bool) cb);
      // Invoke 'cb' with 'true' on connection success, 'false' otherwise.

    virtual ~service() { }
};

service的某些实现是同步的:

struct synchronous_service : service
{
    void connect(std::function<void>(bool) cb) override
    {
        cb(true);
    }
};

其他都是异步的:

struct asynchronous_service : service
{
    void connect(std::function<void>(bool) cb) override
    {
        _thread_pool.post([this, cb]{ cb(true); });
    }
};

我需要创建一个service的包装,其是service本身。这需要线程安全和下保持一定的状态下的mutex

struct wrapped_service : service 
{
    state                    _state;
    std::mutex               _mutex;
    std::unique_ptr<service> _underlying;

    void connect(std::function<void>(bool) cb) override
    {
        std::lock_guard<decltype(_mutex)> guard{_mutex};
        // update `_state`

        _underlying->connect([this, cb]
        {
            std::lock_guard<decltype(_mutex)> guard{_mutex};
            // update `_state`
            cb(true);
        });

        // update `_state`
    }
}

如果_underlying->connect调用始终是异步的,则std::mutex将正常工作。但是,在_underlying->connect是同步的情况下,程序将冻结。

这可以通过使用std::recursive_mutex而不是std::mutex来解决,但是众所周知这是一种代码味道。

这是std::recursive_mutex的有效用例吗?

或者被设计缺陷?请注意,我无法控制service界面。

1 个答案:

答案 0 :(得分:0)

回调有两种模式:立即和延迟。这就要求客户端准备好立即回调并重新进入。这使客户端实现变得复杂。如果您使回调始终处于延迟状态,则无需重新进入客户端。