Question

J'ai une question sur boost::shared_ptr<T>.

Il y a beaucoup de fil.

using namespace boost;

class CResource
{
  // xxxxxx
}

class CResourceBase
{
public:
   void SetResource(shared_ptr<CResource> res)
   {
     m_Res = res;
   }

   shared_ptr<CResource> GetResource()
   {
      return m_Res;
   }
private:
   shared_ptr<CResource> m_Res;
}

CResourceBase base;

//----------------------------------------------
// Thread_A:
    while (true)
    {
       //...
       shared_ptr<CResource> nowResource = base.GetResource();
       nowResource.doSomeThing();
       //...
    }

// Thread_B:
    shared_ptr<CResource> nowResource;
    base.SetResource(nowResource);
    //...

Q1

Si Thread_A ne se soucient pas du nowResource est le plus récent, sera cette partie de code ont problème?

Je veux dire quand Thread_B ne SetResource() complètement, Thread_A obtenir un point intelligent mal par GetResource()?

Q2

Que signifie thread-safe?

Si je ne me soucie pas de savoir si la ressource est plus récente, sera le shared_ptr<CResource> nowResource planter le programme lorsque le nowResource est libéré ou bien le problème détruire le shared_ptr<CResource>?

Était-ce utile?

La solution

De l'augmentation :

  

Les objets de shared_ptr offrent le même   niveau de sécurité de fil comme intégré   les types. Une instance de shared_ptr peut être   « Lire » (lus avec const   opérations) simultanément par plusieurs   threads. Une autre shared_ptr   instances peuvent être « écrites »   (Accessible en utilisant des opérations mutables   comme operator= ou remise à zéro)   simultanément par plusieurs threads   (Même si ces cas sont des copies,   et partager le même nombre de référence   dessous.)

     

Les autres accès simultanés entraînent un comportement non défini.

Ainsi, votre utilisation n'est pas sûr, car il utilise la lecture simultanée et écriture de m_res. Exemple 3 dans la documentation de boost illustre également cela.

Vous devez utiliser une directive mutex qui garde l'accès à m_res dans SetResource / GetResource.

Autres conseils

boost::shared_ptr<> offre un certain niveau de sécurité de fil. Le nombre de références est manipulé dans un fil de manière sûre (sauf si vous configurez boost pour désactiver le support des threads).

Vous pouvez copier un shared_ptr autour et ref_count correctement entretenue. Ce que vous ne pouvez pas le faire en toute sécurité dans plusieurs threads est modifier l'instance réelle de l'objet lui-même shared_ptr de plusieurs threads (comme appeler reset() sur elle de plusieurs threads). Ainsi, votre utilisation n'est pas sûr - vous modifiez l'instance de shared_ptr réelle dans plusieurs threads - vous aurez besoin d'avoir votre propre protection

.

Dans mon code, années shared_ptr sont généralement locaux ou des paramètres passés par valeur, donc il n'y a pas de problème. Incitant d'un fil à l'autre, je l'utilise généralement une file d'attente de thread-safe.

Bien sûr, rien de tout cela traite de la sécurité des threads d'accéder à l'objet pointé par le shared_ptr -. Qui est aussi à vous

Eh bien, TR1 :: shared_ptr (qui est basé sur la poussée) la documentation raconte une histoire différente, ce qui implique que la gestion des ressources est thread-safe, alors que l'accès à la ressource est pas.

» ...

Sécurité des threads

C ++ 0x caractéristiques uniquement sont: rvalue-ref / support de déplacement, le soutien allocateur, constructeur aliasing, make_shared & allocate_shared. De plus, les constructeurs prenant auto_ptr paramètres sont déconseillés en mode C ++ 0x.

La section de sécurité de fil de la documentation shared_ptr Boost dit « objets shared_ptr offrent le même niveau de sécurité de fil comme les types intégrés. » La mise en œuvre doit faire en sorte que les mises à jour simultanées pour séparer les instances shared_ptr sont correctes, même si ces instances partagent un compte de référence par exemple.

shared_ptr (nouveau A); shared_ptr b (a);

// 1 // Discussion Discussion 2

a.reset (); b.reset ();

L'objet allouée dynamiquement doit être détruit par exactement l'un des fils. références faibles rendent les choses encore plus intéressantes. L'état partagé utilisé pour mettre en œuvre shared_ptr doit être transparente pour l'utilisateur et doit être préservée invariants en tout temps. Les éléments clés de l'état partagé sont les comptes de référence forts et faibles. Les mises à jour ces derniers doivent être atomiques et visible à tous les fils pour assurer le nettoyage correct de la ressource gérée (qui est, après tout, le travail de shared_ptr!) Lors de la synchronisation de la mémoire des systèmes multi-processeurs peut être nécessaire pour que les mises à jour compte de référence et la destruction de la ressource gérée sont sans course.

... "

voir http://gcc.gnu.org/onlinedocs /libstdc++/manual/memory.html#std.util.memory.shared_ptr

m_Res est pas ThreadSafe, car il lecture / écriture simultanée, vous avez besoin boost :: fonction atomic_store / charge protège.

//--- Example 3 ---
// thread A
p = p3; // reads p3, writes p
// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write

Ajoutez, votre classe a une condition cyclique des références; le shared_ptr<CResource> m_Res ne peut pas être membre de CResourceBase. Vous pouvez utiliser weak_ptr à la place.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top