Обратные вызовы и `std :: recursive_mutex` - допустимый вариант использования? - PullRequest
0 голосов
/ 01 февраля 2019

У меня есть следующий полиморфный интерфейс:

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 голосов
/ 01 февраля 2019

Существует два режима обратного вызова: немедленный и отложенный.Это требует от клиента быть готовым к немедленному обратному вызову и повторному входу.Это усложняет реализацию клиента.Если вы выполняете обратный вызов всегда с задержкой, это устраняет необходимость повторного входа клиента.

...