2012-12-13 21 views
5

Có thể di chuyển an toàn unique_ptr bằng C++ 11 hoạt động nguyên tử không?Chủ đề an toàn unique_ptr di chuyển

Hiện nay tôi có một mã như thế này

std::unique_ptr<SyncToken> DataManager::borrowSyncToken() 
{ 
    std::unique_lock<std::mutex> syncTokenLock(syncTokenMutex); 
    return std::move(syncToken); 
} 

Tôi tự hỏi liệu có một số cách thanh lịch hơn, như chỉ đơn giản tuyên bố:

std::atomic<std::unique_ptr<SyncToken>> syncToken; 

và tránh sự cần thiết của mutex. Hoặc có lẽ tôi không cần phải quan tâm đến khóa ở đây cả và std :: di chuyển đã là nguyên tử?

Sau khi nghiên cứu tôi đã thực hiện cho đến nay có vẻ như với tôi:

  • std :: di chuyển bản thân không phải là nguyên tử và cần phải có một số đồng bộ xung quanh khác 2 chủ đề kêu gọi phương pháp của tôi đồng thời có thể kết thúc với 2 bản của một số con trỏ không xác định.
  • std :: khai báo nguyên tử biên dịch cho tôi, nhưng tôi không biết cách khởi tạo và thực hiện di chuyển.

Trả lời

2

Không, điều này là không thể.

Giá trị T mà bạn chuyển đến std::atomic cần phải được sao chép một cách trivially, trong đó std::unique_ptr thì không. Các hoạt động như std::atomic::load hoặc std::atomic::store lấy đối tượng T theo giá trị.

Đóng gói thứ gì đó trong một số std::atomic cũng không thực hiện các thao tác từ giá trị nguyên tử.

Khi sử dụng std::unique_ptr trong ngữ cảnh nguyên tử, bạn phải suy nghĩ về thực tế là bạn có thể gặp sự cố khi nói đến quản lý tài nguyên. Bạn không bao giờ biết có bao nhiêu chủ đề vẫn đề cập đến dữ liệu của bạn, vấn đề này có thể được giải quyết với một số std::shared_ptr sử dụng đếm tham chiếu nguyên tử. (Bạn cần phải kiểm tra xem nó có thực sự nguyên tử hay không bằng cách sử dụng hàm std::atomic_is_lock_free.)

Một điều tôi cũng ngại khi nhìn vào mã của bạn là ý định của hàm borrowSyncToken. Nó được gọi là vay nhưng bạn chuyển quyền sở hữu mã thông báo cho người gọi bằng cách di chuyển ra khỏi số std::unique_ptr, quyền sở hữu được trả lại như thế nào và các chủ đề khác nhận được gì khi DataManager hiện không sở hữu mã thông báo?

+0

Cảm ơn bạn đã trả lời và thảo luận về tiêu chuẩn :: shared_ptr. Vì mục đích: mã được đơn giản hóa, nhưng tôi nghĩ rằng ngay cả như vậy nó sẽ trả về nullptr cho các chủ đề sau này cho phép một người gọi để tìm ra rằng mã thông báo không có sẵn. Vấn đề được giải quyết ở đây tôi sẽ giải thích trong bình luận khác. –

+0

Khách hàng thực hiện hai loại thao tác trên DataManager: đọc, viết. Chỉ có một khách hàng có thể viết trong thời gian đó. ** Khách hàng không phải là chủ đề ** - đôi khi có, đôi khi có thể có một công việc nền được đưa ra cho khách hàng. việc đọc/ghi không có nghĩa là một thao tác đơn giản mà theo một giao thức truyền thông phức tạp giữa DataManager và máy khách. Các yêu cầu của khách hàng không nhất thiết phải bị chặn cho đến khi có sẵn mã thông báo nhưng đôi khi vẫn bị từ chối. Để định hướng trong đống lộn xộn, tôi đã đề xuất SyncToken này - nhà văn cần mượn SyncToken và gọi returnSyncToken (unique_ptr ) khi hoàn tất. –