通过使用覆盖操作员的代理来同步对象

Synchronizing an object by using a proxy that overrides operator->

本文关键字:代理 同步 对象 操作员 覆盖      更新时间:2023-10-16

我有一些可以从多个线程访问的对象,需要同步。

我想要的解决方案涉及创建一个代理类,覆盖其operator->,并锁定对operator->的调用。这大约是我想要的:

template <typename T>
class SynchronizedObject<T> {
    lock_t l;
    public:
    ??? operator->() {
        lock(l);
        // do the operation
        unlock(l);
    }
};

因此,例如,我可以轻松地制作一个同步向量,例如SynchronizedObject<std::vector>,并打电话给push_back等。

但是,当我进行了一些研究时,这并不是operator->的过载的工作方式,因为在我的示例中,它需要返回T*,只有在返回后,只有在返回后,请致电push_back或任何方法我'我感兴趣。有什么办法可以实现我想要的,而无需访问宏地狱?

这是一个概念证明,它利用operator ->的递归行为透明地插入锁定代理。代理是不可移动的,不可分配的,因此不能意外存储(或者您确实必须是指)。

#include <iostream>
template <class T>
struct LockedPtr {
    LockedPtr(T *_t) {
        std::cout << "lockn";
    }
    ~LockedPtr() {
        std::cout << "unlockn";
    }
    LockedPtr(LockedPtr const &) = delete;
    LockedPtr &operator = (LockedPtr const &) = delete;
    T* operator -> () {
        return _t;
    }
private:
    T *_t;
};
template <class T>
struct LockWrapper {
    LockedPtr<T> operator -> () {
        return {&_t};
    }
    private:
    T _t;
};
struct DummyContainer {
    void push_back(int i) {
        std::cout << "push_back(" << i << ")n";
    }
};
int main() {
    LockWrapper<DummyContainer> lv;
    lv->push_back(1);
    lv->push_back(2);
    lv->push_back(3);
}

输出:

lock
push_back(1)
unlock
lock
push_back(2)
unlock
lock
push_back(3)
unlock