Ihtiyacım olan işi bir liste ile uzun, shared_ptr ve poor_ptr buldum. Benim sorunum, bir ana bilgisayarın dahili verileriyle etkileşim kurmak isteyen birkaç müşterim vardı. Genellikle, ana bilgisayar verileri kendi başına güncelleştirir, ancak bir istemci isterse, ana bilgisayar verilerine erişene kadar ana bilgisayarın güncelleştirmeyi durdurması gerekir. Aynı zamanda, bir istemci özel erişim isteyebilir, böylece başka hiçbir istemci veya ana bilgisayar bu ana bilgisayar verilerini değiştiremez.
Bunu nasıl yaptım, bir yapı oluşturdum:
struct UpdateLock
{
typedef std::shared_ptr< UpdateLock > ptr;
};
Her müşterinin böyle bir üyesi olacaktır:
UpdateLock::ptr m_myLock;
Daha sonra ana bilgisayarda münhasırlık için bir zayıf_ptr üyesi ve münhasır olmayan kilitler için bir zayıf_ptr listesi bulunur:
std::weak_ptr< UpdateLock > m_exclusiveLock;
std::list< std::weak_ptr< UpdateLock > > m_locks;
Kilidi etkinleştirmek için bir işlev ve ana bilgisayarın kilitli olup olmadığını kontrol etmek için başka bir işlev vardır:
UpdateLock::ptr LockUpdate( bool exclusive );
bool IsUpdateLocked( bool exclusive ) const;
LockUpdate, IsUpdateLocked ve periyodik olarak ana bilgisayarın Update yordamındaki kilitleri test ediyorum. Bir kilidi sınamak için shor_ptr süresinin dolup dolmadığını kontrol etmek ve m_locks listesinden süresi dolmuş herhangi bir şeyi kaldırmak kadar basittir (bunu sadece ana bilgisayar güncellemesi sırasında yaparım), listenin boş olup olmadığını kontrol edebilirim; Aynı zamanda, bir istemci asılı kaldıkları paylaşılan_ptr'i sıfırladığında otomatik kilidini açıyorum, bu da bir istemci otomatik olarak yok edildiğinde gerçekleşir.
Hepsinden önemlisi, müşteriler nadiren münhasırlığa ihtiyaç duyduklarından (genellikle yalnızca eklemeler ve silme işlemleri için ayrılmıştır), çoğu zaman LockUpdate (yanlış), yani münhasır olmayan bir istek (! M_exclusiveLock) kadar başarılı olur. Ve bir LockUpdate (true), münhasırlık isteği, sadece (! M_exclusiveLock) ve (m_locks.empty ()) hem de başarılı olur.
Özel ve münhasır olmayan kilitler arasında hafifletmek için bir kuyruk eklenebilir, ancak şimdiye kadar herhangi bir çarpışma yaşamadım, bu yüzden çözümü eklemek için bekleyin (çoğunlukla gerçek dünya test koşulum var).
Şimdiye kadar bu benim ihtiyaçlarım için iyi çalışıyor; Bunu genişletme ihtiyacını ve genişletilmiş kullanımda ortaya çıkabilecek bazı sorunları hayal edebiliyorum, ancak bu uygulanması hızlıydı ve çok az özel kod gerektiriyordu.