Ich fand, dass shared_ptr und schwaches_ptr, ein langes mit einer Liste, die Arbeit erledigten, die ich brauchte. Mein Problem war, dass ich mehrere Clients hatte, die mit den internen Daten eines Hosts interagieren wollten. In der Regel aktualisiert der Host die Daten selbst. Wenn ein Client dies anfordert, muss der Host die Aktualisierung jedoch beenden, bis keine Clients mehr auf die Hostdaten zugreifen. Gleichzeitig kann ein Client einen exklusiven Zugriff anfordern, sodass weder andere Clients noch der Host diese Hostdaten ändern können.
Wie ich das gemacht habe, habe ich eine Struktur erstellt:
struct UpdateLock
{
typedef std::shared_ptr< UpdateLock > ptr;
};
Jeder Kunde hätte ein Mitglied von folgenden:
UpdateLock::ptr m_myLock;
Dann hätte der Host ein schwaches_Ptr-Mitglied für Exklusivität und eine Liste von schwachen_Ptrs für nicht exklusive Sperren:
std::weak_ptr< UpdateLock > m_exclusiveLock;
std::list< std::weak_ptr< UpdateLock > > m_locks;
Es gibt eine Funktion zum Aktivieren der Sperre und eine andere Funktion zum Überprüfen, ob der Host gesperrt ist:
UpdateLock::ptr LockUpdate( bool exclusive );
bool IsUpdateLocked( bool exclusive ) const;
Ich teste in LockUpdate, IsUpdateLocked und regelmäßig in der Update-Routine des Hosts auf Sperren. Das Testen auf eine Sperre ist so einfach wie das Überprüfen, ob der schwache_PTR abgelaufen ist, und das Entfernen von abgelaufenen Dateien aus der m_Locks-Liste (ich mache dies nur während des Host-Updates). Ich kann überprüfen, ob die Liste leer ist. Gleichzeitig wird die automatische Entsperrung automatisch aktiviert, wenn ein Client das shared_ptr zurücksetzt, an dem er festhält. Dies geschieht auch, wenn ein Client automatisch zerstört wird.
Der Gesamteffekt ist, dass Clients selten Exklusivität benötigen (normalerweise nur für Hinzufügungen und Löschungen reserviert). Meistens ist eine Anforderung an LockUpdate (false), dh nicht exklusiv, erfolgreich, solange (! M_exclusiveLock). Und ein LockUpdate (true), eine Anfrage nach Exklusivität, ist nur erfolgreich, wenn sowohl (! M_exclusiveLock) als auch (m_locks.empty ()).
Es könnte eine Warteschlange hinzugefügt werden, um zwischen exklusiven und nicht exklusiven Sperren abzumildern. Bisher gab es jedoch keine Kollisionen. Daher möchte ich warten, bis die Lösung hinzugefügt wird (meistens, damit ich eine reale Testbedingung habe).
Bisher funktioniert dies gut für meine Bedürfnisse; Ich kann mir vorstellen, dass dies erweitert werden muss, und einige Probleme, die bei einer erweiterten Verwendung auftreten können, waren jedoch schnell zu implementieren und erforderten nur sehr wenig benutzerdefinierten Code.