Làm thế nào std :: nguyên tử được thực hiện cho các loại phi nguyên tử?


8

Tôi tự hỏi làm thế nào có thể std::atomic_refđược thực hiện một cách hiệu quả ( std::mutexmỗi đối tượng) cho các đối tượng phi nguyên tử vì thuộc tính sau có vẻ khá khó thực thi:

Các hoạt động nguyên tử được áp dụng cho một đối tượng thông qua một nguyên tử là các nguyên tử đối với các hoạt động nguyên tử được áp dụng thông qua bất kỳ nguyên tử nào khác tham chiếu đến cùng một đối tượng.

Cụ thể, đoạn mã sau:

void set(std::vector<Big> &objs, size_t i, const Big &val) {
    std::atomic_ref RefI{objs[i]};
    RefI.store(val);
}

Có vẻ khá khó để thực hiện vì std::atomic_refsẽ cần phải bằng cách nào đó chọn mỗi lần giống nhau std::mutex(trừ khi đó là một khóa chính lớn được chia sẻ bởi tất cả các đối tượng cùng loại).

Tui bỏ lỡ điều gì vậy? Hoặc mỗi đối tượng chịu trách nhiệm thực hiện std::atomic_refvà do đó là nguyên tử hoặc mang một std::mutex?


2
Họ có thể có một bản đồ địa chỉ và mutexs và giao diện của mutex liên quan đến địa chỉ đối tượng. Điều này cho phép nhiều tham chiếu khác nhau để bảo vệ một đối tượng.
NathanOliver

Câu trả lời:


5

Việc thực hiện là khá nhiều chính xác giống như std::atomic<T>chính nó. Đây không phải là một vấn đề mới.

Xem khóa ở đâu cho một std :: nguyên tử? Một triển khai điển hình của std::atomic/ std::atomic_refmột bảng băm tĩnh của các khóa, được lập chỉ mục theo địa chỉ, cho các đối tượng không khóa. Va chạm băm chỉ dẫn đến tranh chấp thêm, không phải là một vấn đề chính xác. (Bế tắc vẫn không thể thực hiện được; các khóa chỉ được sử dụng bởi các chức năng nguyên tử không bao giờ cố gắng thực hiện 2 lần một lần.)

Trên GCC chẳng hạn, std::atomic_refchỉ là một cách khác để gọi __atomic_stoređối tượng. (Xem hướng dẫn sử dụng GCC: nội dung nguyên tử )

Trình biên dịch biết liệu Tcó đủ nhỏ để không bị khóa hay không. Nếu không, nó gọi hàm thư viện libatomic sẽ sử dụng khóa.

(sự thật thú vị: điều đó có nghĩa là nó chỉ hoạt động nếu đối tượng có đủ căn chỉnh cho atomic<T>. Nhưng trên nhiều nền tảng 32 bit bao gồm x86, uint64_tcó thể chỉ có căn chỉnh 4 byte. atomic_refTrên một đối tượng như vậy sẽ biên dịch và chạy, nhưng thực tế không phải là nguyên tử nếu trình biên dịch sử dụng tải / lưu trữ 8 byte SSE ở chế độ 32 bit để thực hiện nó. May mắn thay, không có mối nguy hiểm nào cho các đối tượng alignof(T) == sizeof(T), giống như hầu hết các kiểu nguyên thủy trên kiến ​​trúc 64 bit.)


Tôi đã không nhận ra atomic<T>được cho phép trên các loại phi nguyên tử (mặc dù người ta có thể tự phân bổ về mặt kỹ thuật mutex, vì nó sở hữu đối tượng). Cảm ơn đã giải thích, nó có ý nghĩa.
Nonyme

6

Việc triển khai có thể sử dụng hàm băm dựa trên địa chỉ của đối tượng để xác định tập hợp khóa nào cần lấy trong khi thực hiện thao tác.


Đây thực sự là cách libstdc ++ thực hiện các hoạt động nguyên tử trên shared_ptrcác đối tượng. github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/src/ Kẻ
Brian

Bảng băm cho biết sẽ chứa mutexes? Khi nào họ an toàn để miễn phí?
Nonyme

@Nonymouse Trong liên kết tôi cung cấp, bạn có thể thấy rằng họ có thời lượng lưu trữ tĩnh.
Brian
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.