Question

Quelqu'un sait-il où je peux trouver une implémentation qui enveloppe un std :: map et le rend thread-safe? Lorsque je dis thread safe, je veux dire qu'il n'offre qu'un accès série à la carte, thread par nœud. De manière optimale, cette carte doit utiliser uniquement les constructions standard-library et / ou boost.

Était-ce utile?

La solution

Ne correspond pas aux critères que vous avez spécifiés, mais vous pouvez consulter les conteneurs TBB . Il existe ce que l’on appelle concurrent_hash_map , qui permet à plusieurs threads d’accéder simultanément aux données de la carte. Il y a quelques détails, mais tout est bien documenté et peut vous donner une idée du "conteneur simultané". En fonction de vos besoins, cela pourrait être totalement inapproprié ...

Autres conseils

En règle générale, il n'est pas judicieux que les classes de collection fournissent une sécurité des threads, car elles ne peuvent pas savoir comment elles sont utilisées. Vous serez bien mieux servi en mettant en œuvre vos propres mécanismes de verrouillage dans les constructions de niveau supérieur qui utilisent les collections.

Le boost shared_mutex fournirait la meilleure approche à lecteurs multiples / auteur unique pour emballer une carte standard en fonction de vos contraintes. Je ne connais pas de " pré-construit " implémentations qui marient ces deux car la tâche est généralement triviale.

Cela dépend de l'application à implémenter. Un " thread-safe " map effectuerait des appels individuels dans la mappe thread-safe, mais de nombreuses opérations doivent être effectuées sur des appels thread-safe . L’application qui utilise la carte doit associer un mutex à la carte et utiliser ce mutex pour coordonner les accès.

Essayer de créer des conteneurs thread-safe était une erreur en Java et ce serait une erreur en C ++.

Essayez cette bibliothèque

http://www.codeproject.com/KB/threads/lwsync.aspx

Il est implémenté dans une approche moderne basée sur une stratégie c ++.

Voici quelques extraits du lien pour illustrer l'idée avec la casse "vecteur"

typedef lwsync::critical_resource<std::vector<int> > sync_vector_t;
sync_vector_t vec;

// some thread:
{
   // Critical resource can be naturally used with STL containers.
   sync_vector_t::const_accessor vec_access = vec.const_access();
   for(std::vector<int>::const_iterator where = vec_access->begin();
         where != vec_access->end();
         ++where;
        )
   std::cout << *where << std::endl;
}

sync_vector_t::accessor some_vector_action()
{
   sync_vector_t::accessor vec_access = vec.access();
   vec_access->push_back(10);
   return vec_access;
   // Access is escalated from within a some_vector_action() scope
   // So that one can make some other action with vector before it becomes
   // unlocked.
}

{
   sync_vector_t::accessor vec_access = some_vector_action();
   vec_access->push_back(20);
   // Elements 10 and 20 will be placed in vector sequentially.
   // Any other action with vector cannot be processed between those two
   // push_back's.
}

Je suis venu avec ceci (qui, je suis sûr, peut être amélioré pour prendre plus de deux arguments):

template<class T1, class T2>
class combine : public T1, public T2
{
public:

    /// We always need a virtual destructor.
    virtual ~combine() { }
};

Cela vous permet de faire:

// Combine an std::mutex and std::map<std::string, std::string> into
// a single instance.
combine<std::mutex, std::map<std::string, std::string>> lockableMap;

// Lock the map within scope to modify the map in a thread-safe way.
{
    // Lock the map.
    std::lock_guard<std::mutex> locked(lockableMap);

    // Modify the map.
    lockableMap["Person 1"] = "Jack";
    lockableMap["Person 2"] = "Jill";
}

Si vous souhaitez utiliser std :: recursive_mutex et std :: set, cela fonctionnera aussi.

Il existe une proposition ici (de ma part - plug sans vergogne) qui encapsule les objets (y compris les conteneurs STL ) pour un accès sécurisé (à coût nul) des threads:

https://github.com/isocpp/CppCoreGuidelines/issues/924

  

L'idée de base est très simple. Quelques classes wrapper sont utilisées pour appliquer le verrouillage en lecture / écriture et présenter simultanément une vue const (en lecture seule) ou non-const (en lecture-écriture) de l'objet enveloppé.

     

L'idée est de rendre impossible, lors de la compilation, l'accès incorrect à une ressource partagée entre les threads.

Le code d'implémentation peut être trouvé ici:

https://github.com/galik/GSL / blob / lockable-objects / include / gsl / gsl_lockable

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