Я нашел, что shared_ptr и weak_ptr, длинный со списком, выполнил работу, в которой я нуждался. Моя проблема заключалась в том, что у меня было несколько клиентов, желающих взаимодействовать с внутренними данными хоста. Обычно хост обновляет данные самостоятельно, однако, если клиент запрашивает его, хост должен прекратить обновление, пока клиенты не получат доступ к данным хоста. В то же время клиент может запросить монопольный доступ, чтобы ни другие клиенты, ни хост не могли изменить эти данные хоста.
Как я это сделал, я создал структуру:
struct UpdateLock
{
typedef std::shared_ptr< UpdateLock > ptr;
};
У каждого клиента будет такой член:
UpdateLock::ptr m_myLock;
Тогда у хоста будет элемент weak_ptr для исключительности и список слабых_приятий для неисключительных блокировок:
std::weak_ptr< UpdateLock > m_exclusiveLock;
std::list< std::weak_ptr< UpdateLock > > m_locks;
Существует функция для включения блокировки и другая функция для проверки, заблокирован ли хост:
UpdateLock::ptr LockUpdate( bool exclusive );
bool IsUpdateLocked( bool exclusive ) const;
Я проверяю блокировки в LockUpdate, IsUpdateLocked и периодически в процедуре обновления хоста. Тестирование на блокировку так же просто, как проверка, истек ли срок действия weak_ptr, и удаление всех просроченных из списка m_locks (я делаю это только во время обновления хоста), я могу проверить, пуст ли список; в то же время, я получаю автоматическую разблокировку, когда клиент сбрасывает shared_ptr, за который он висит, что также происходит, когда клиент автоматически уничтожается.
Общий эффект заключается в том, что клиенты редко нуждаются в эксклюзивности (обычно зарезервированы только для добавления и удаления), большую часть времени запрос к LockUpdate (false), то есть неисключительный, выполняется до тех пор, пока (! M_exclusiveLock). И LockUpdate (true), запрос на эксклюзивность, успешно выполняется только тогда, когда оба (! M_exclusiveLock) и (m_locks.empty ()).
Можно было бы добавить очередь для смягчения исключительных и неисключительных блокировок, однако у меня до сих пор не было коллизий, поэтому я собираюсь подождать, пока это произойдет, чтобы добавить решение (в основном, поэтому у меня есть условия тестирования в реальном мире).
Пока это хорошо работает для моих нужд; Я могу представить необходимость его расширения и некоторые проблемы, которые могут возникнуть при расширенном использовании, однако, это было быстро реализовано и требовало очень мало пользовательского кода.