Encontré que shared_ptr y weak_ptr, un largo con una lista, hicieron el trabajo que necesitaba. Mi problema era que tenía varios clientes que querían interactuar con los datos internos de un host. Por lo general, el host actualiza los datos por sí mismo, sin embargo, si un cliente lo solicita, el host debe dejar de actualizarse hasta que ningún cliente acceda a los datos del host. Al mismo tiempo, un cliente puede solicitar acceso exclusivo, de modo que ningún otro cliente, ni el host, puedan modificar los datos del host.
Cómo hice esto fue, creé una estructura:
struct UpdateLock
{
typedef std::shared_ptr< UpdateLock > ptr;
};
Cada cliente tendría un miembro de tales:
UpdateLock::ptr m_myLock;
Luego, el host tendría un miembro weak_ptr para exclusividad y una lista de weak_ptrs para bloqueos no exclusivos:
std::weak_ptr< UpdateLock > m_exclusiveLock;
std::list< std::weak_ptr< UpdateLock > > m_locks;
Hay una función para habilitar el bloqueo y otra función para verificar si el host está bloqueado:
UpdateLock::ptr LockUpdate( bool exclusive );
bool IsUpdateLocked( bool exclusive ) const;
Compruebo los bloqueos en LockUpdate, IsUpdateLocked y periódicamente en la rutina de actualización del host. Probar un bloqueo es tan simple como verificar si los débiles_ptr han expirado, y eliminar cualquier vencido de la lista m_locks (solo hago esto durante la actualización del host), puedo verificar si la lista está vacía; Al mismo tiempo, obtengo desbloqueo automático cuando un cliente restablece el shared_ptr en el que están colgando, lo que también ocurre cuando un cliente se destruye automáticamente.
El efecto general es que, dado que los clientes rara vez necesitan exclusividad (generalmente reservado solo para adiciones y eliminaciones), la mayoría de las veces una solicitud a LockUpdate (falso), es decir, no exclusiva, tiene éxito siempre que (! M_exclusiveLock). Y un LockUpdate (verdadero), una solicitud de exclusividad, tiene éxito solo cuando ambos (! M_exclusiveLock) y (m_locks.empty ()).
Se podría agregar una cola para mitigar entre bloqueos exclusivos y no exclusivos, sin embargo, no he tenido colisiones hasta ahora, por lo que tengo la intención de esperar hasta que eso suceda para agregar la solución (principalmente para tener una condición de prueba del mundo real).
Hasta ahora esto está funcionando bien para mis necesidades; Puedo imaginar la necesidad de expandir esto, y algunos problemas que podrían surgir sobre el uso expandido, sin embargo, esto fue rápido de implementar y requirió muy poco código personalizado.