次のポリモーフィック インターフェイスがあります。
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
インターフェイスを制御できないことに注意してください。