我有以下可移动但不可复制的类,可用于同步对某些共享资源的访问:
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 库的移动模拟时,是否可以保证这种移动锁的想要的行为?旧的编译器不支持新标准。
是的。您可以通过以下方式自行验证:
#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());
}