2010-03-26 37 views
6

Trong boost::shared_ptr destructor, điều này được thực hiện:Tại sao bộ đếm tham chiếu không tăng :: shared_ptr volatile?

if(--*pn == 0) 
{ 
    boost::checked_delete(px); 
    delete pn; 
} 

nơi pn là một con trỏ đến quầy tham khảo, được typedefed như

shared_ptr::count_type -> detail::atomic_count -> long 

tôi dự kiến ​​sẽ có các longvolatile long, được đưa ra sử dụng luồng và 0-kiểm tra và xóa không nguyên tử trong trình phá hủy shared_ptr ở trên. Tại sao nó không dễ bay hơi?

EDIT:

Hóa ra tôi nhìn vào tiêu đề sử dụng khi sử dụng đa luồng không được xác định (atomic_count.hpp). Trong atomic_count_win32.hpp, phần giảm được triển khai đúng cho việc sử dụng đa luồng.

+0

Bạn tìm mã này ở đâu? – jalf

+0

@jalf: shared_ptr_nmt.hpp –

Trả lời

16

Bởi vì volatile không cần thiết cho đa luồng, và không có gì có lợi, nhưng có khả năng phá hủy một số tối ưu hóa.

Để đảm bảo truy cập đa luồng an toàn cho một biến, nguyên thủy chúng ta cần là rào cản bộ nhớ, cung cấp cả bảo đảm volatile và một số khác (ngăn chặn truy nhập bộ nhớ sắp xếp lại qua hàng rào, do)

Tôi tin rằng shared_ptr sử dụng các hoạt động nguyên tử khi có thể, điều này ngầm cung cấp rào cản bộ nhớ. Nếu không nó sẽ trở lại một mutex, nó cũng cung cấp một rào cản bộ nhớ.

Xem Why is volatile not considered useful in multithreaded C or C++ programming? hoặc http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/ để biết thêm chi tiết

Sửa
count_typekhông một long trong trường hợp tổng quát. Đó là có thể chuyển đổi thành long. Nếu bạn nhìn vào atomic_count.hpp, typedef to long chỉ được áp dụng nếu không có luồng có sẵn (trong trường hợp này tất nhiên, không cần đồng bộ hóa). Nếu không, công cụ sẽ sử dụng triển khai được xác định trong boost/smart_ptr/detail/atomic_count_pthreads.hpp hoặc boost/smart_ptr/detail/atomic_count_win32.hpp hoặc một trong các tệp khác được liệt kê. Và đó là những lớp bao bọc đồng bộ đảm bảo mọi hoạt động được thực hiện một cách nguyên tử.

+0

"Tôi tin rằng shared_ptr sử dụng các hoạt động nguyên tử khi có thể" - không phải trong ví dụ được trích dẫn của tôi với destructor, đó là vấn đề của tôi bây giờ ... –

+0

Vâng, làm cho biến 'volatile' sẽ không thay đổi gì cả. Bạn đang phải, giảm và so sánh một dài chống lại không có vẻ nguy hiểm, nhưng nó phụ thuộc vào những gì * phần còn lại * của lớp con trỏ đang làm. – jalf

+0

@jalf: Vâng, đó là bạn đã mất tôi.;-) Ngay bây giờ, trong ví dụ của tôi, hai chủ đề nhập dD shared_ptr và "phần còn lại của lớp con trỏ" không làm gì khác. –

8

volatile hầu như không có gì liên quan đến luồng. Xem here.

+0

Bạn có nói rằng không có vấn đề gì với việc xử lý ở trên bộ đếm trong bộ hủy, nếu được thực hiện trên các luồng khác nhau? –

2

Bạn đang đọc sai mã. atomic_count được định nghĩa đơn giản là dài nếu mã không sử dụng đa luồng:

#ifndef BOOST_HAS_THREADS 

namespace boost 
{ 

namespace detail 
{ 

typedef long atomic_count; 

} 

} 

#elif //... include various platform-specific headers that define atomic_count class 

#endif 
+0

Cảm ơn! Đã chỉnh sửa câu hỏi để làm rõ mọi thứ. (Đã chấp nhận câu trả lời của jalf) –

Các vấn đề liên quan