Verrouillage lecteur / graveur interprocess avec Boost

Ce fil de discussion est précieux pour expliquer comment implémenter des verrous de lecteur / graveur avec Boost. Cela semble relativement simple et je l’aime vraiment beaucoup, mais il semble également utiliser un verrou non nommé et j’ai besoin d’une solution interprocess (n’a pas besoin d’être portable, mais uniquement de Windows).

Est-il possible d’avoir un interprocess shared_mutex ? Je vois qu’il y a un named_mutex mais je ne peux pas le faire fonctionner avec shared_lock autres verrous.

Tous les indicateurs sont appréciés.

[MODIFIER]

En attendant, je suis tombé sur ce fil qui touche presque le bout des doigts. J’ai deux problèmes:

  1. il ne montre pas le code complet (je suppose que je dois utiliser named_upgradable_mutex mais je ne suis pas tout à fait sûr) et
  2. Je n’aime pas la réponse du “writer” modifié, qui n’utilise pas de classe standard permettant de déverrouiller dans destructor, mais une séquence de 3 appels bruts sur le mutex.

Les commentaires ou les bonnes solutions sont toujours les bienvenus.

La documentation Boost.Interprocess décrit les soi-disant mutex évolutifs pris en charge et les opérations mutex extensible pour les deux types de mutex extensible pris en charge:

  • boost::interprocess::interprocess_upgradable_mutex , un mutex extensible anonyme, non récursif, pouvant être placé dans la mémoire partagée ou dans des fichiers mappés en mémoire.
  • boost::interprocess::named_upgradable_mutex , un mutex extensible nommé non récursif.

EDIT: Je crois que cela fonctionne:

 #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  // http://stackoverflow.com/questions/12439099/interprocess-reader-writer-lock-with-boost/ #define SHARED_MEMORY_NAME "SO12439099-MySharedMemory" struct shared_data { private: typedef boost::interprocess::interprocess_upgradable_mutex upgradable_mutex_type; mutable upgradable_mutex_type mutex; volatile int counter; public: shared_data() : counter(0) { } int count() const { boost::interprocess::sharable_lock lock(mutex); return counter; } void set_counter(int counter) { boost::interprocess::scoped_lock lock(mutex); this->counter = counter; } }; int main(int argc, char *argv[]) { using namespace boost::interprocess; if (argc != 2) { std::cerr << "Usage: " << argv[0] << " WHICH" << std::endl; return 1; } const std::string which = argv[1]; if (which == "parent") { shared_memory_object::remove(SHARED_MEMORY_NAME); shared_memory_object shm(create_only, SHARED_MEMORY_NAME, read_write); BOOST_SCOPE_EXIT(argc) { shared_memory_object::remove(SHARED_MEMORY_NAME); } BOOST_SCOPE_EXIT_END; shm.truncate(sizeof (shared_data)); // Map the whole shared memory into this process. mapped_region region(shm, read_write); // Construct the shared_data. new (region.get_address()) shared_data; // Go to sleep for a minute. sleep(60); return 0; } else if (which == "reader_child") { shared_memory_object shm(open_only, SHARED_MEMORY_NAME, read_write); mapped_region region(shm, read_write); shared_data& d = *static_cast(region.get_address()); for (int i = 0; i < 100000; ++i) { std::cout << "reader_child: " << d.count() << std::endl; } } else if (which == "writer_child") { shared_memory_object shm(open_only, SHARED_MEMORY_NAME, read_write); mapped_region region(shm, read_write); shared_data& d = *static_cast(region.get_address()); for (int i = 0; i < 100000; ++i) { d.set_counter(i); std::cout << "writer_child: " << i << std::endl; } } } 

J'ai essayé ceci sur un Mac avec le script suivant:

 #!/usr/bin/env sh ./a.out reader_child & ./a.out reader_child & ./a.out writer_child & ./a.out reader_child & ./a.out reader_child & 

(Vous devez d'abord commencer par le parent: ./a.out parent )

La sortie indiquait un entrelacement des lignes "reader_child" et "writer_child" (toutes les lignes "reader_child" indiquant une valeur non nulle après la première ligne "writer_child"), ce qui semble fonctionner.