我具有以下多态接口:
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
界面。
答案 0 :(得分:0)
回调有两种模式:立即和延迟。这就要求客户端准备好立即回调并重新进入。这使客户端实现变得复杂。如果您使回调始终处于延迟状态,则无需重新进入客户端。