Я знайшов shared_ptr і слабкий_ptr, довгий зі списком, зробив потрібну мені роботу. Моя проблема полягала в тому, що у мене було кілька клієнтів, які бажають взаємодіяти з внутрішніми даними хоста. Зазвичай хост оновлює дані самостійно, однак, якщо клієнт цього вимагає, хосту потрібно припинити оновлення, поки жоден клієнт не отримає доступ до даних хоста. У той же час, клієнт може попросити ексклюзивний доступ, щоб ні інші клієнти, ні хост не могли змінювати ці дані хосту.
Як я це зробив, я створив структуру:
struct UpdateLock
{
typedef std::shared_ptr< UpdateLock > ptr;
};
У кожного клієнта буде такий член:
UpdateLock::ptr m_myLock;
Тоді хост матиме слабкий_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 та періодично в ході оновлення хосту. Тестування блокування настільки ж просто, як перевірити, чи закінчився термін дії слабкого коду, і видалити будь-який термін дії зі списку m_locks (я це роблю лише під час оновлення хоста), я можу перевірити, чи список порожній; в той же час, я отримую автоматичне розблокування, коли клієнт скидає shared_ptr, на який він висить, що також відбувається, коли клієнт автоматично знищується.
Ефект, що переважає все, полягає в тому, що клієнтам рідко потрібна ексклюзивність (як правило, зарезервована лише для доповнень та видалень), більшість часу запит на LockUpdate (помилковий), тобто неексклюзивний, досягає успіху до тих пір, як (! M_exclusiveLock). І LockUpdate (true), запит на ексклюзивність, є успішним лише тоді, коли і (! M_exclusiveLock), і (m_locks.empty ()).
Для зменшення між ексклюзивними та неексклюзивними блокуваннями може бути додана черга, однак у мене досі не було зіткнень, тому я маю намір почекати, поки це станеться, щоб додати рішення (здебільшого, щоб я мав умову тестування в реальному світі).
Поки це добре працює для моїх потреб; Я можу собі уявити необхідність розширити це, і деякі проблеми, які можуть виникнути при розширеному використанні, однак це було швидко реалізувати і вимагало дуже мало спеціального коду.