使用覆盖operator-gt;的代理同步对象

时间:2015-05-09 10:20:28

标签: c++ multithreading

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

我想要的解决方案涉及创建代理类,覆盖其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或我感兴趣的任何方法。有没有什么方法可以实现我想要的,而不必访问宏观地狱?

1 个答案:

答案 0 :(得分:2)

这是一个概念证明,它利用operator ->的递归行为来透明地插入锁定代理。代理是不可移动的,不可分配的,因此无法意外存储(或者你真的必须意味着它)。

#include <iostream>

template <class T>
struct LockedPtr {
    LockedPtr(T *_t) {
        std::cout << "lock\n";
    }

    ~LockedPtr() {
        std::cout << "unlock\n";
    }

    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