C++ 回调和“std::recursive\u mutex”-有效的用例?

C++ 回调和“std::recursive\u mutex”-有效的用例?,c++,multithreading,c++11,mutex,recursive-mutex,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() { } }; 其他是异步的: struct synchronous_service : service { voi

我有以下多态接口:

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

    virtual ~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); });
    }
};
如果
\u底层->connect
调用始终是异步的,那么
std::mutex
将正常工作。但是,如果
\u undernative->connect
是同步的,程序将冻结

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

这是
std::recursive\u互斥体的有效用例吗?


还是设计有缺陷?请注意,我无法控制
服务
接口。

有两种回调模式:立即和延迟。这要求客户机准备好立即回调并重新进入。这使客户机实现复杂化。如果您使回调总是延迟,从而消除了客户端重新进入的需要。

鉴于您的限制,我认为这是合法的。小错误:您需要将
\u互斥体
传递到
锁保护
构造函数中。在同步情况下不能传递不同的回调吗?@Galik:什么意思?我不知道底层的
\是同步的还是异步的。如果回调总是锁定互斥锁,那么在调用
连接(cb)
之前,你不能简单地释放任何锁,如果是同步的,你可以保证在
连接(cb)结束之前,cb已经完成(并释放了锁)呼叫并安全地重新获取锁。如果它是异步的,那么无论如何重新获取锁应该是安全的,因为它将位于不同的线程上。这在您的场景中有效吗?@Galik:
\u底层->连接
不保证线程安全。两个不同的线程可以同时调用
wrapped\u services::connect
。如果
\u基础->连接
未受保护,则可能存在数据竞争。
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`
    }
}