Eu tenho uma classe móvel, mas não copiável, que pode ser usada para sincronizar o acesso a alguns recursos compartilhados:
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;
}
}
A idéia aqui é que essa estrutura possa ser movida, mantendo o mutex e liberando automaticamente o bloqueio após sair do escopo. O uso pretendido é o seguinte:
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);
}
A questão é se esse comportamento desejado de mover o bloqueio é garantido ao usar a emulação de movimentação da biblioteca boost com um compilador C++ 03 com o qual estamos presos neste projeto? O compilador antigo não tem suporte para os padrões mais recentes.
Sim. Veja como você mesmo pode verificar isso:
Ao vivo no Coliru
Porém, observe estes: Ponteiros de bloqueio e valores sincronizados