Tôi tìm thấy shared_ptr và yếu_ptr, một danh sách dài, đã thực hiện công việc tôi cần. Vấn đề của tôi là, tôi đã có một số khách hàng muốn tương tác với dữ liệu nội bộ của máy chủ lưu trữ. Thông thường, máy chủ tự cập nhật dữ liệu, tuy nhiên, nếu máy khách yêu cầu, máy chủ cần dừng cập nhật cho đến khi không có máy khách nào truy cập dữ liệu máy chủ. Đồng thời, một khách hàng có thể yêu cầu quyền truy cập độc quyền, để không có khách hàng nào khác, cũng như máy chủ lưu trữ có thể sửa đổi dữ liệu máy chủ đó.
Làm thế nào tôi làm điều này là, tôi đã tạo ra một cấu trúc:
struct UpdateLock
{
typedef std::shared_ptr< UpdateLock > ptr;
};
Mỗi khách hàng sẽ có một thành viên như vậy:
UpdateLock::ptr m_myLock;
Sau đó, máy chủ lưu trữ sẽ có một thành viên yếu_ptr để độc quyền và một danh sách các yếu tố_ptrs cho các khóa không độc quyền:
std::weak_ptr< UpdateLock > m_exclusiveLock;
std::list< std::weak_ptr< UpdateLock > > m_locks;
Có một chức năng để cho phép khóa và một chức năng khác để kiểm tra xem máy chủ có bị khóa hay không:
UpdateLock::ptr LockUpdate( bool exclusive );
bool IsUpdateLocked( bool exclusive ) const;
Tôi kiểm tra các khóa trong LockUpdate, IsUpdateLocked và định kỳ trong thói quen Cập nhật của máy chủ. Việc kiểm tra khóa cũng đơn giản như kiểm tra xem điểm yếu đã hết hạn và xóa bất kỳ khóa nào đã hết hạn khỏi danh sách m_locks (tôi chỉ thực hiện việc này trong quá trình cập nhật máy chủ), tôi có thể kiểm tra xem danh sách có trống không; đồng thời, tôi nhận được mở khóa tự động khi máy khách đặt lại shared_ptr mà chúng đang treo, điều này cũng xảy ra khi máy khách bị hủy tự động.
Hiệu quả trên tất cả là, vì khách hàng hiếm khi cần độc quyền (thường chỉ dành cho bổ sung và xóa), nên phần lớn thời gian yêu cầu LockUpdate (sai), nghĩa là không độc quyền, thành công miễn là (! M_exinatingLock). Và LockUpdate (đúng), yêu cầu độc quyền, chỉ thành công khi cả (! M_exinatingLock) và (m_locks.empty ()).
Một hàng đợi có thể được thêm vào để giảm thiểu giữa các khóa độc quyền và không độc quyền, tuy nhiên, cho đến nay tôi không có va chạm nào, vì vậy tôi dự định sẽ đợi cho đến khi điều đó xảy ra để thêm giải pháp (chủ yếu là tôi có điều kiện thử nghiệm trong thế giới thực).
Cho đến nay điều này đang hoạt động tốt cho nhu cầu của tôi; Tôi có thể tưởng tượng sự cần thiết phải mở rộng điều này và một số vấn đề có thể phát sinh khi sử dụng mở rộng, tuy nhiên, việc này được thực hiện nhanh chóng và yêu cầu rất ít mã tùy chỉnh.