J'ai trouvé que shared_ptr et low_ptr, un long avec une liste, ont fait le travail dont j'avais besoin. Mon problème était que plusieurs clients souhaitaient interagir avec les données internes d'un hôte. En règle générale, l'hôte met à jour les données de lui-même, cependant, si un client le demande, l'hôte doit arrêter la mise à jour jusqu'à ce qu'aucun client n'accède aux données de l'hôte. En même temps, un client peut demander un accès exclusif, de sorte qu'aucun autre client, ni l'hôte, ne puisse modifier ces données d'hôte.
Comment j'ai fait cela, j'ai créé une structure:
struct UpdateLock
{
typedef std::shared_ptr< UpdateLock > ptr;
};
Chaque client aurait un membre de tel:
UpdateLock::ptr m_myLock;
Ensuite, l'hôte aurait un membre faible_ptr pour l'exclusivité, et une liste de points faibles pour les verrous non exclusifs:
std::weak_ptr< UpdateLock > m_exclusiveLock;
std::list< std::weak_ptr< UpdateLock > > m_locks;
Il existe une fonction pour activer le verrouillage et une autre fonction pour vérifier si l'hôte est verrouillé:
UpdateLock::ptr LockUpdate( bool exclusive );
bool IsUpdateLocked( bool exclusive ) const;
Je teste les verrous dans LockUpdate, IsUpdateLocked et périodiquement dans la routine de mise à jour de l'hôte. Tester un verrou est aussi simple que de vérifier si le low_ptr a expiré et de supprimer tout expiré de la liste m_locks (je ne le fais que pendant la mise à jour de l'hôte), je peux vérifier si la liste est vide; en même temps, j'obtiens un déverrouillage automatique lorsqu'un client réinitialise le shared_ptr auquel il s'accroche, ce qui se produit également lorsqu'un client est détruit automatiquement.
L'effet global est que, puisque les clients ont rarement besoin d'exclusivité (généralement réservée aux ajouts et aux suppressions uniquement), la plupart du temps une demande à LockUpdate (false), c'est-à-dire non exclusive, réussit tant que (! M_exclusiveLock). Et un LockUpdate (true), une demande d'exclusivité, ne réussit que lorsque (! M_exclusiveLock) et (m_locks.empty ()).
Une file d'attente pourrait être ajoutée pour atténuer les verrous exclusifs et non exclusifs, cependant, je n'ai eu aucune collision jusqu'à présent, donc j'ai l'intention d'attendre que cela se produise pour ajouter la solution (surtout, j'ai donc une condition de test dans le monde réel).
Jusqu'à présent, cela fonctionne bien pour mes besoins; Je peux imaginer la nécessité d'étendre cela, et certains problèmes qui pourraient survenir lors d'une utilisation étendue, cependant, cela a été rapide à implémenter et n'a nécessité que très peu de code personnalisé.