Supposons que j'ai une classe:Est-ce que le constructeur move a un sens pour une classe dont les champs std :: thread's et std :: mutex sont?
class WonnaBeMovedClass
{
public:
WonnaBeMovedClass(WonnaBeMovedClass&& other);
void start();
private:
void updateSharedData();
std::vector<int> _sharedData;
std::thread _threadUpdate;
std::mutex _mutexShaderData;
//other stuff
};
WonnaBeMovedClass::WonnaBeMovedClass(WonnaBeMovedClass&& other)
{
_sharedData = std::move(other._sharedData);
_threadUpdate = std::move(other._threadUpdate);
_mutexShaderData = std::move(other._mutexShaderData); //won't compile.
}
void WonnaBeMovedClass::start()
{
_threadUpdate = std::thread(&updateSharedData, this);
}
void WonnaBeMovedClass::updateSharedData()
{
std::lock_guard<std::mutex> lockSharedData(_mutexShaderData);
for (auto& value : _sharedData)
{
++value;
}
}
Il ne compilera pas parce que mutex ne peut être déplacé. Cela n'a pas de sens. Je pensais qu'il est possible de contourner cela en utilisant des pointeurs au lieu des variables réelles et est venu avec les éléments suivants:
class WonnaBeMovedClass
{
public:
WonnaBeMovedClass(WonnaBeMovedClass&& other);
void start();
private:
void updateSharedData();
std::vector<int> _sharedData;
std::unique_ptr<std::thread> _threadUpdate //pointer;
std::unique_ptr<std::mutex> _mutexShaderData //pointer;
//other stuff
};
WonnaBeMovedClass::WonnaBeMovedClass(WonnaBeMovedClass&& other)
{
_sharedData = std::move(other._sharedData);
_threadUpdate = std::move(other._threadUpdate);
_mutexShaderData = std::move(other._mutexShaderData); //won't compile.
}
void WonnaBeMovedClass::start()
{
_threadUpdate = std::make_unique<std::thread>(&updateSharedData, this);
}
void WonnaBeMovedClass::updateSharedData()
{
std::lock_guard<std::mutex> lockSharedData(*_mutexShaderData);
for (auto& value : _sharedData)
{
++value;
}
}
Alors maintenant, quand je:
WonnaBeMovedClass object1;
WonnaBeMovedClass object2;
//do stuff
object1 = std::move(object2);
Je propose en fait les adresses des deux mutex et le fil. Ça a plus de sens maintenant ... Ou pas?
Le thread travaille toujours avec les données de object1, pas object2, donc cela n'a toujours aucun sens. J'ai peut-être déplacé le mutex, mais le thread n'est pas conscient de object2. Ou est-ce? Je suis incapable de trouver la réponse et je vous demande de l'aide. Est-ce que je fais quelque chose de complètement faux et copier/déplacer des threads et des mutex est juste un mauvais design et je devrais repenser l'architecture du programme?
Edit:
Il y avait une question sur le but réel de la classe. Il s'agit en fait d'un client TCP/IP (représenté en tant que classe) qui contient:
- dernières données du serveur (plusieurs tables de données, similaires à std :: vector).
- contient des méthodes qui gèrent les unités d'exécution (état de mise à jour, envoi/réception de messages).
Plus d'une connexion peut être établie à la fois, donc quelque part dans un code il y a un champ std::vector<Client>
qui représente toutes les connexions actives. Les connexions sont déterminées par le fichier de configuration.
//read configurations
...
//init clients
for (auto& configuration : _configurations)
{
Client client(configuration);
_activeClients.push_back(client); // this is where compiler reminded me that I am unable to move my object (aka WonnaBeMovedClass object).
}}
J'ai changé _activeClients
std::vector<Client>
-std::vector<std::unique_ptr<Client>>
et modifié le code d'initialisation pour créer des objets pointeur au lieu d'objets directement et travaillé autour de mes questions, mais la question reste donc je décidé de poster ici.
votre approche avec le pointeur ne compilera pas non plus, ou est votre commentaire un reste? – gsamaras
en double de https://stackoverflow.com/questions/7557179/move-constructor-for-stdmutex? –
Vous pouvez créer un wrapper de style PImpl pour le premier cas. La seconde approche peut également fonctionner, mais vous devrez créer '_mutexShaderData'. – VTT