2014-09-11 15 views
6

std::shared_ptr được đảm bảo an toàn chỉ. Tôi không biết cơ chế triển khai điển hình sử dụng để đảm bảo điều này, nhưng chắc chắn nó phải có một số chi phí. Và chi phí đó sẽ có mặt ngay cả trong trường hợp ứng dụng của bạn là đơn luồng.Chi phí từ shared_ptr là an toàn chỉ là gì?

Trường hợp trên có đúng không? Và nếu vậy, điều đó có nghĩa là nó vi phạm nguyên tắc "bạn không trả tiền cho những gì bạn không sử dụng", nếu bạn không sử dụng các đảm bảo an toàn chủ đề?

+0

Từ bộ nhớ, thư viện Loki có con trỏ thông minh với chính sách an toàn chủ đề, giải quyết mối quan ngại này. –

+0

FYI, http://stackoverflow.com/questions/15129263/is-there-a-non-atomic-equivalent-of-stdshared-ptr-and-why-isnt-there-one-in –

Trả lời

4

Ít nhất trong mã tăng cường trên i386, boost::shared_ptr được triển khai bằng cách sử dụng hoạt động CAS nguyên tử. Điều này có nghĩa rằng trong khi nó có một số chi phí, nó là khá thấp. Tôi mong đợi bất kỳ triển khai nào của std::shared_ptr cũng tương tự.

Trong các vòng lặp chặt chẽ trong mã số hiệu suất cao, tôi tìm thấy một số tăng tốc bằng cách chuyển sang con trỏ thô và thực sự cẩn thận. Nhưng đối với mã bình thường - tôi sẽ không lo lắng về nó.

+1

Tôi khá chắc chắn tất cả các triển khai chính đều sử dụng nguyên tử. Tôi biết của Microsoft, cho một. –

+0

@VioletGiraffe: Không phải tất cả nền tảng phần cứng đều hỗ trợ các bộ đếm nguyên tử không khóa. Ví dụ: ARM cũ hơn không. –

+2

Hoạt động nguyên tử khá tốn kém. Thời gian qua tôi đo, tôi tin rằng nó thường là khoảng 20 ns cho mỗi hoạt động nguyên tử trên một CPU Intel điển hình. Theo thứ tự chậm hơn 100 lần so với hoạt động thường xuyên. –

8

Nếu chúng ta kiểm tra cppreference trang cho std::shared_ptr họ nêu rõ sau trong Thực hiện ghi nhận phần:

Để đáp ứng yêu cầu an toàn thread, các quầy tham khảo thường được tăng lên và giảm đi bằng std::atomic::fetch_add với std::memory_order_relaxed.

Thật thú vị khi lưu ý một thực hiện thực tế, ví dụ như tài liệu libstdc++ thực hiện here nói:

Đối với phiên bản của shared_ptr trong libstdC++ trình biên dịch và thư viện được cố định, mà làm những điều đơn giản hơn nhiều : chúng tôi có một CAS nguyên tử hoặc chúng tôi không, hãy xem Chính sách khóa bên dưới để biết chi tiết.

Các Chọn Khóa Chính sách phần nói (nhấn mạnh tôi):

Có một lớp _Sp_counted_base duy nhất, mà là một mẫu tham số trên enum __gnu_cxx :: _ Lock_policy. Toàn bộ gia đình lớp học được tham số hóa trên chính sách khóa, phải lên đến __shared_ptr, __weak_ptr và __enable_shared_from_this. Lớp std :: shared_ptr thực tế kế thừa từ __shared_ptr với tham số chính sách khóa được chọn tự động dựa trên mô hình luồng và nền tảng libstdC++ được định cấu hình để mẫu chuyên nghiệp có sẵn tốt nhất sẽ được sử dụng. Thiết kế này là cần thiết vì nó sẽ không phù hợp với shared_ptr để có thêm một tham số mẫu , ngay cả khi nó có giá trị mặc định. Các chính sách có sẵn là:

[...]

3._S_Single

chính sách này sử dụng một add_ref_lock không reentrant() mà không khóa. Nó được sử dụng khi libstdC++ được xây dựng mà không có chủ đề --enable.

và tiếp tục nói (nhấn mạnh tôi):

Đối với tất cả ba chính sách, gia tăng số lượng tài liệu tham khảo và suất này được thực hiện thông qua các chức năng trong ext/atomicity.h, mà phát hiện nếu chương trình là đa luồng. Nếu chỉ có một luồng thực hiện tồn tại trong chương trình thì các hoạt động phi nguyên tử ít tốn kém hơn được sử dụng.

Vì vậy, ít nhất trong việc triển khai này, bạn không trả tiền cho những gì bạn không sử dụng.

+1

"memory_order_relaxed \t Hoạt động thoải mái: không có sự ràng buộc về đặt hàng hoặc đồng bộ hóa, chỉ yêu cầu tính nguyên tử của thao tác này". Điều đó không * không * đúng! – curiousguy

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