2010-01-29 9 views
4

Je songe à utiliser boost :: weak_ptr pour implémenter un pool d'objets tel qu'ils seront récoltés quand personne n'utilise l'un des objets. Ma préoccupation, cependant, est que c'est un environnement multithread, et il semble qu'il y ait une condition de concurrence entre le dernier shared_ptr à un objet qui sort de la portée et un nouveau shared_ptr construit à partir de weak_ptr. Normalement, vous protégez de telles opérations avec un verrou ou quelque chose comme ça; cependant, le point entier ici est que vous ne savez pas quand le shared_ptr pourrait être hors de portée. Ai-je mal compris quelque chose à propos de boost :: shared_ptr et boost :: weak_ptr? Si non, quelqu'un a-t-il de bonnes suggestions sur ce qu'il faut faire?Boost weak_ptr dans un programme multithread pour implémenter un pool de ressources

Merci.

Andrew

Répondre

9

Pour utiliser un weak_ptr, vous devez normalement saisir une référence forte en construisant un shared_ptr avec elle. Cette dernière étape est atomique: soit vous obtenez une référence forte, soit vous obtenez une exception bad_weak_ptr. (Vous pouvez également appeler lock() sur le weak_ptr et soit obtenir une référence forte ou nulle.)

Exemple (avec lock(), assez facile d'adapter à l'autre style):

void do_something(weak_ptr<foo> weak) { 
    // Grab strong reference 
    shared_ptr<foo> strong(weak.lock()); 
    if (strong) { 
     // We now have a strong reference to use 
    } else { 
     // No strong references left; object already freed 
    } 
} 
+3

Je crois qu'il n'est pas nécessaire de tester si votre shared_ptr est valide ou non, car le constructeur va lancer des exceptions bad_weak_ptr si votre week_ptr pointe sur l'objet supprimé. Ou vous devriez utiliser weak_ptr :: lock() qui ne lance pas mais peut retourner un shared_ptr qui pointe vers NULL. – Serge

+1

Alors c'est atomique? La section sur la sécurité des threads dans la page de manuel laisse planer un doute dans mon esprit. –

+0

@Serge: Merci! Je vais réparer mon message. –

0

Oui, ish. En termes d'accès aux pointeurs, Boost aurait dû tout mettre en sécurité; cela fait partie de leur point. Cependant, si vous attendez un délai entre le moment où le dernier shared_ptr s'éteint et le moment où vous voulez créer le suivant, vous obtiendrez un pointeur nul. (Si vous vérifiez de manière appropriée, vous devriez alors avoir un cas d'échec appropro).

Mais vous ne pouvez pas finir avec un shared_ptr invalide

3

Les deux boost::weak_ptr et boost::shared_ptr sont similaires si elle vient d'enfiler la sécurité: ils sont pas thread-safe s'il y a un risque que l'objet va être détruit quelque part . Si votre objet référencé dans boost::shared_ptr ou weak_ptr est référencé de façon permanente quelque part, alors vous pouvez utiliser shared/weak ptrs sans aucun risque.

Mais si une opération va déréférencer le dernier exemple vivant de l'objet, puis à ce moment-là, vous ne pouvez pas faire des opérations sur weak_ptr: en particulier: vous ne pouvez pas affecter weak_ptr à un autre weak_ptr parce qu'il utilise shared_ptr en interne. En outre, vous ne pouvez pas utiliser le verrou car le résultat n'est pas défini. En outre, expired() méthode est inutile de: il peut retourner la valeur true, mais la prochaine ligne de votre code, votre objet peut-être déjà expiré.

Questions connexes