Синхронизировать объект - PullRequest
0 голосов
/ 06 июня 2019

Наличие объекта с обширным списком API.

Каков наилучший способ синхронизации этого объекта, т. Е. Объект уже существует в устаревшем коде и используется в сотнях строк кода.

Наивный способ - обернуть каждый вызов API к объекту std::mutex. Есть ли более простой или элегантный способ сделать это?

Я попробовал приведенный ниже код, однако хотел бы узнать мнение об этом или альтернативные решения.

Ниже представлен класс-оболочка шаблона, который автоматически блокирует объект во время использования. то есть блокирует объект при создании и разблокирует при разрушении.

Этот шаблон очень похож на блокировку области, однако он полезен только для статических объектов / синглетонов, он не будет работать для разных экземпляров данного объекта

template <typename T> class Synced
{
    static std::mutex _lock;
    T& _value;
    public:
    Synced(T& val) : _value(val)
    {
        std::cout << "lock" << endl;
        _lock.lock();
    }

    virtual ~Synced()
    {
        std::cout << "unlock" << endl;
        _lock.unlock();
    }

    T& operator()()
    {
        return _value;
    }
};

template <class T> std::mutex Synced<T>::_lock;

пример класса для использования с синхронизированным шаблоном класса это может быть примером класса, упомянутого выше, с десятками API

class Board
{
    public:
    virtual ~Board() { cout << "Test dtor " << endl; }
    void read() { cout << "read" << endl; }
    void write() { cout << "write" << endl; }
    void capture() { cout << "capture" << endl; }

};

пример использования, базовые вызовы, объект Synced не ограничен областью действия, поэтому деструктор вызывается сразу после точки с запятой

int main(int argc, char* argv[]) 
{
    Board b;


    Synced<Board>(t)().read();
    cout <<"  " <<  endl;

    Synced<Board>(t)().write();
    cout << "  " << endl;

    Synced<Board>(t)().capture();
    cout << "  " << endl;

    return 1;
}

Здесь ниже вывод приведенного выше примера выполнения:

lock
read
unlock

lock
write
unlock

lock
capture
unlock

Test dtor

1 Ответ

0 голосов
/ 06 июня 2019

Я использую мьютексы только для очень маленьких критических секций, возможно, для нескольких строк кода, и только если я контролирую все возможные состояния ошибки. Для сложного API вы можете получить мьютекс в неожиданном состоянии. Я склонен решать такие вещи с помощью схемы реактора . Будет ли это практичным, зависит от того, можете ли вы разумно использовать сериализацию / десериализацию для этого объекта. Если вам нужно написать сериализацию самостоятельно, подумайте о таких вещах, как стабильность и сложность API. Я лично предпочитаю zeromq для такого рода вещей, когда это удобно, ваш пробег может варьироваться.

...