在 C++03 编译器上使用移动模拟将 boost::unique_lock 作为返回值从函数中移出是否安全?

问题描述 投票:0回答:1

我有以下可移动但不可复制的类,可用于同步对某些共享资源的访问:

class wrapper_with_lock{
    private:
        BOOST_MOVABLE_BUT_NOT_COPYABLE(wrapper_with_lock)
        boost::unique_lock l;
    public:
        int* data1;//These point to data that needs to have synchronized access
        char* data2;//....
        wrapper_with_lock(boost::mutex& m) : l(m){}//Constructor acquires the lock
        wrapper_with_lock(BOOST_RV_REF(wrapper_with_lock) x) {
            l = boost::move(x.l);//Move the lock
            data1 = x.data1;//Move the pointers
            x.data1 = 0;
            ....
        }
        wrapper_with_lock& operator=(BOOST_RV_REF(wrapper_with_lock) x) // Move assign
        {
            if (this != &x){
                l = boost::move(x.l);//Move the lock and other data
                ....
            }
            return *this;
        }
}

这里的想法是,这个结构可以四处移动,保存互斥锁,并在超出范围后自动释放锁。预期用途如下:

wrapper_with_lock do_some_init(boost::mutex& m){
    wrapper_with_lock w(m);
    *(w.data1) = 1234;//Do something initially with the data etc...
    //Return the lock holding object by moving it (should move the internal lock).
    //The lock should be valid and properly moved to the caller
    //of this function inside the wrapper
    return boost::move(w);
}

问题是,当我们在这个项目中使用带有 C++03 编译器的 boost 库的移动模拟时,是否可以保证这种移动锁的想要的行为?旧的编译器不支持新标准。

boost move-semantics c++03 boost-mutex
1个回答
0
投票

是的。您可以通过以下方式自行验证:

住在Coliru

#include <boost/move/move.hpp>
#include <boost/thread.hpp>
#include <boost/thread/locks.hpp>

class wrapper_with_lock {
  private:
    BOOST_MOVABLE_BUT_NOT_COPYABLE(wrapper_with_lock)
    boost::unique_lock<boost::mutex> l;

  public:
    int*  data1; // These point to data that needs to have synchronized access
    char* data2; //....

    ~wrapper_with_lock() {
        delete[] data1;
        delete[] data2;
    }

    wrapper_with_lock(boost::mutex& m)
        : l(m)
        , data1(new int[1024])
        , data2(new char[1024]) {} // Constructor acquires the lock

    wrapper_with_lock(BOOST_RV_REF(wrapper_with_lock) x) {
        bool was_locked = x.locked();
        assert(was_locked); // actually invariant of wrapper_with_lock?

        l = boost::move(x.l); // Move the lock

        assert(!x.locked());
        assert(was_locked == locked());

        data1   = x.data1;          // Move the pointers
        x.data1 = 0;
        data2   = x.data2;          // Move the pointers
        x.data2 = 0;
    }

    bool locked() const { return l.owns_lock(); }

    wrapper_with_lock& operator=(BOOST_RV_REF(wrapper_with_lock) x) // Move assign
    {
        if (this != &x) {
            bool was_locked = x.locked();
            assert(was_locked);   // actually invariant of wrapper_with_lock?

            l = boost::move(x.l); // Move the lock and other data

            assert(!x.locked());
            assert(was_locked == locked());
            //....
            data1   = x.data1; // Move the pointers
            x.data1 = 0;
            data2   = x.data2; // Move the pointers
            x.data2 = 0;
        }
        return *this;
    }
};

wrapper_with_lock do_some_init(boost::mutex& m){
    wrapper_with_lock w(m);
    *w.data1 = 1234; // Do something initially with the data etc...

    // Return the lock holding object by moving it (should move the internal lock).
    // The lock should be valid and properly moved to the caller
    // of this function inside the wrapper
    return boost::move(w);
}

int main() {
    boost::mutex m;
    wrapper_with_lock l = do_some_init(m);
    assert(l.locked());
}

请查看这些:锁定指针同步值

© www.soinside.com 2019 - 2024. All rights reserved.