Ho trovato shared_ptr e weak_ptr, un lungo con un elenco, fatto il lavoro di cui avevo bisogno. Il mio problema era che avevo diversi clienti che volevano interagire con i dati interni di un host. In genere, l'host aggiorna i dati da solo, tuttavia, se un client lo richiede, l'host deve interrompere l'aggiornamento fino a quando nessun client accede ai dati dell'host. Allo stesso tempo, un client potrebbe richiedere l'accesso esclusivo, in modo che nessun altro client, né l'host, possa modificare i dati dell'host.
Come ho fatto, ho creato una struttura:
struct UpdateLock
{
typedef std::shared_ptr< UpdateLock > ptr;
};
Ogni cliente avrebbe un membro di tale:
UpdateLock::ptr m_myLock;
Quindi l'host avrebbe un membro weak_ptr per esclusività e un elenco di weak_ptrs per blocchi non esclusivi:
std::weak_ptr< UpdateLock > m_exclusiveLock;
std::list< std::weak_ptr< UpdateLock > > m_locks;
Esiste una funzione per abilitare il blocco e un'altra funzione per verificare se l'host è bloccato:
UpdateLock::ptr LockUpdate( bool exclusive );
bool IsUpdateLocked( bool exclusive ) const;
Testare i blocchi in LockUpdate, IsUpdateLocked e periodicamente nella routine di aggiornamento dell'host. Testare un blocco è semplice come controllare se il punto debole è scaduto e rimuovere eventuali scaduti dall'elenco m_locks (lo faccio solo durante l'aggiornamento dell'host), posso verificare se l'elenco è vuoto; allo stesso tempo, ottengo lo sblocco automatico quando un client reimposta il shared_ptr a cui si sta aggrappando, cosa che accade anche quando un client viene distrutto automaticamente.
L'effetto complessivo è che, poiché i client raramente necessitano di esclusività (in genere riservata solo a aggiunte ed eliminazioni), il più delle volte una richiesta a LockUpdate (false), vale a dire non esclusiva, ha successo fino a quando (! M_exclusiveLock). E un LockUpdate (true), una richiesta di esclusività, riesce solo quando entrambi (! M_exclusiveLock) e (m_locks.empty ()).
È possibile aggiungere una coda per mitigare i blocchi esclusivi e non esclusivi, tuttavia finora non ho avuto collisioni, quindi ho intenzione di aspettare fino a quando ciò accadrà per aggiungere la soluzione (principalmente quindi ho una condizione di test nel mondo reale).
Finora questo funziona bene per le mie esigenze; Posso immaginare la necessità di espandere questo, e alcuni problemi che potrebbero sorgere su un uso esteso, tuttavia, questo è stato veloce da implementare e ha richiesto pochissimo codice personalizzato.