ฉันพบ shared_ptr และจุดอ่อน_ptrซึ่งมีรายการยาว ๆ ได้งานที่ฉันต้องการ ปัญหาของฉันคือฉันมีลูกค้าหลายรายที่ต้องการโต้ตอบกับข้อมูลภายในของโฮสต์ โดยปกติโฮสต์จะอัปเดตข้อมูลด้วยตัวเองอย่างไรก็ตามหากไคลเอ็นต์ร้องขอโฮสต์จำเป็นต้องหยุดการอัปเดตจนกว่าจะไม่มีไคลเอ็นต์เข้าถึงข้อมูลโฮสต์ ในขณะเดียวกันไคลเอนต์สามารถขอการเข้าถึงแบบเอกสิทธิ์เฉพาะบุคคลเพื่อไม่ให้ไคลเอนต์อื่นหรือโฮสต์สามารถแก้ไขข้อมูลโฮสต์นั้นได้
ฉันทำสิ่งนี้ได้อย่างไรฉันสร้างโครงสร้าง:
struct UpdateLock
{
typedef std::shared_ptr< UpdateLock > ptr;
};
ลูกค้าแต่ละรายจะมีสมาชิกดังต่อไปนี้:
UpdateLock::ptr m_myLock;
จากนั้นโฮสต์จะมีสมาชิกจุดอ่อนสำหรับการผูกขาดและรายชื่อจุดอ่อนสำหรับการล็อกที่ไม่ผูกขาด:
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 และเป็นระยะในกิจวัตรการอัปเดตของโฮสต์ การทดสอบการล็อกนั้นง่ายมากเพียงแค่ตรวจสอบว่าจุดอ่อน_ptrหมดอายุหรือไม่และลบส่วนที่หมดอายุออกจากรายการ m_locks (ฉันทำสิ่งนี้ในระหว่างการอัปเดตโฮสต์เท่านั้น) ฉันสามารถตรวจสอบว่ารายการว่างเปล่าหรือไม่ ในเวลาเดียวกันฉันจะได้รับการปลดล็อกอัตโนมัติเมื่อไคลเอนต์รีเซ็ต shared_ptr ที่พวกเขาแขวนอยู่ซึ่งจะเกิดขึ้นเมื่อไคลเอนต์ถูกทำลายโดยอัตโนมัติ
ผลกระทบทั้งหมดคือเนื่องจากไคลเอนต์แทบไม่ต้องการความพิเศษ (โดยทั่วไปสงวนไว้สำหรับการเพิ่มและการลบเท่านั้น) โดยส่วนใหญ่แล้วการร้องขอเพื่อ LockUpdate (เท็จ) กล่าวคือไม่ผูกขาด แต่จะประสบความสำเร็จตราบเท่าที่ (! m_exclusiveLock) และ LockUpdate (true) ซึ่งเป็นคำขอสำหรับการผูกขาดจะสำเร็จก็ต่อเมื่อทั้ง (! m_exclusiveLock) และ (m_locks.empty ())
สามารถเพิ่มคิวเพื่อลดการล็อกระหว่างการล็อกแบบพิเศษและแบบไม่ผูกขาดได้อย่างไรก็ตามจนถึงขณะนี้ฉันไม่มีการชนกันดังนั้นฉันจึงตั้งใจที่จะรอจนกว่าสิ่งนั้นจะเกิดขึ้นเพื่อเพิ่มโซลูชัน (ส่วนใหญ่ฉันจึงมีเงื่อนไขการทดสอบในโลกแห่งความเป็นจริง)
จนถึงตอนนี้มันทำงานได้ดีสำหรับความต้องการของฉัน ฉันสามารถจินตนาการได้ถึงความจำเป็นในการขยายสิ่งนี้และปัญหาบางอย่างที่อาจเกิดขึ้นจากการใช้งานแบบขยายอย่างไรก็ตามสิ่งนี้ใช้งานได้รวดเร็วและต้องการโค้ดที่กำหนดเองเพียงเล็กน้อย