2010-05-01 33 views
6

Thư viện chủ đề C++ 0x hoặc Boost.thread xác định hàm mẫu không phải thành viên variadic khóa tất cả khóa tránh khóa chết.Tại sao không có ổ khóa phạm vi cho nhiều mutexes trong C++ 0x hoặc Boost.Thread?

template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...); 

Trong khi chức năng này tránh được bế tắc, tiêu chuẩn không bao gồm khóa có phạm vi liên quan để viết mã an toàn ngoại lệ.

{ 
    std::lock(l1,l2); 
    // do some thing 
    // unlock li l2 exception safe 
} 

Điều đó có nghĩa rằng chúng ta cần phải sử dụng cơ chế khác như khối try-catch để làm cho ngoại lệ đang an toàn hoặc xác định khóa scoped của chúng ta trên nhiều mutexes mình hoặc thậm chí làm điều đó

{ 
    std::lock(l1,l2); 
    std::unique_lock lk1(l1, std::adopted); 
    std::unique_lock lk2(l2, std::adopted); 
    // do some thing 
    // unlock li l2 on destruction of lk1 lk2 
} 

Tại sao tiêu chuẩn không bao gồm một khóa chỉnh phạm vi trên nhiều mutexes cùng loại, như ví dụ

{ 
    std::array_unique_lock<std::mutex> lk(l1,l2); 
    // do some thing 
    // unlock l1 l2 on destruction of lk 
} 

hoặc tuples của mutexes

01.
{ 
    std::tuple_unique_lock<std::mutex, std::recursive_mutex> lk(l1,l2); 
    // do some thing 
    // unlock l1 l2 on destruction of lk 
} 

Có điều gì sai về thiết kế không?


Cập nhật: mô tả từ các tiêu chuẩn

template <class L1, class L2, class... L3> void lock(L1&, L2&, L3&...); 

Yêu cầu: Mỗi kiểu mẫu tham số phải đáp ứng các yêu cầu Mutex, ngoại trừ một cuộc gọi đến try_- khóa() có thể ném một ngoại lệ . [Lưu ý: Mẫu lớp unique_lock đáp ứng các yêu cầu này khi được khởi tạo phù hợp. —end note]

Hiệu ứng: Tất cả đối số được khóa thông qua một chuỗi các cuộc gọi đến khóa(), try_lock() hoặc mở khóa() trên mỗi đối số. Trình tự các cuộc gọi sẽ không dẫn đến bế tắc, nhưng nếu không thì không xác định. [Lưu ý: Thuật toán tránh tắc nghẽn như try-and-back-off phải được sử dụng, nhưng thuật toán cụ thể không được chỉ định để tránh việc triển khai quá hạn chế. —end note] Nếu một cuộc gọi để khóa() hoặc try_lock() ném một ngoại lệ, mở khóa() sẽ được gọi cho bất kỳ đối số nào đã bị khóa bởi một cuộc gọi đến lock() hoặc try_lock().


Tôi chấp nhận câu trả lời. Tôi hiểu rằng lý do chính là vì không có đủ thời gian để làm cho thư viện chủ đề C++ 0x tốt hơn. Tôi hy vọng rằng TR2 sẽ bao gồm nhiều thứ hơn.

+1

Câu hỏi hay, tôi không thấy lý do tại sao không có một số 'scoped_multi_lock (T ...)'. –

+1

Thật vậy, có vẻ như với tôi các hàm 'lock (...)' bị mất cân bằng. Tôi ít nhất cũng mong đợi tương đương 'mở khóa (...)'. Dường như là nơi tốt nhất để thêm chức năng như vậy vào lớp 'lock_guard'. Trong đó nó có thể được xây dựng với nhiều Lockables và mở khóa chúng khi phá hủy. Trái với nhiều lớp mẫu khác. – GrafikRobot

+0

@Grafik Bạn nói đúng. mở khóa cũng phải được trên tiêu chuẩn. Sự khác biệt là mở khóa (...) không thể bế tắc. –

Trả lời

3

Tôi nghĩ rằng bằng cách cung cấp defer_lock_t (và adopt_lock_t) kỳ vọng là việc sử dụng đó sẽ như thế nào ví dụ thứ hai của bạn, hoặc có thể hơn như:

std::unqiue_lock ul1(l1, std::deferred); 
std::unique_lock ul2(l2, std::deferred); 
std::lock(ul1, ul2); 

Đây là ngoại lệ an toàn và tất cả những thứ tốt.

Tôi chắc chắn không thể giả vờ biết được suy nghĩ của các nhà thiết kế, nhưng tôi đoán là họ đang nỗ lực cung cấp một bộ tối thiểu di động, an toàn, nguyên thủy.Một loại khóa nhiều kiểu scoped chỉ là quá nhiều đóng băng, và nó đóng băng rằng nếu trong tiêu chuẩn cần phải được xác định và thiết kế, hoặc trong boost.thread, đóng băng cần phải được thực hiện (và tất nhiên cuối cùng tiêu chuẩn phải được quan tâm về thực hiện quá, hãy xem những gì đã xảy ra với xuất khẩu).

+0

'export' là một thể loại hoàn toàn khác và (sẽ có) yêu cầu thay đổi kiến ​​trúc lớn trong trình biên dịch. Tại sao bạn nghĩ rằng nó cần quá nhiều đóng băng? Nó chỉ nên viết một lần về mặt nguyên thủy đã được đưa ra. –

+0

@Logan Rất tiếc, tôi đã sử dụng lỗi để sử dụng thay vì accept_lock. –

+0

@gf, đó là vấn đề của tôi. Nó _is_ viết một lần về các nguyên thủy đã được đưa ra, đó là những gì làm cho nó đóng băng, đó là lý do tại sao nó không cần phải được trong tiêu chuẩn hoặc một gánh nặng cho những người thực hiện. –

-1

Xây dựng một đối tượng khóa nhiều ổ khóa không tránh bất kỳ khóa chết nào ngoài việc khóa riêng từng khóa. Bạn không thể khóa hai ổ khóa cùng một lúc .. trừ khi bạn sử dụng hai chủ đề, loại đánh bại điểm. Điều này đúng ngay cả khi bạn đặt chúng trong cùng một tuyên bố.

+3

Vui lòng xem tiêu chuẩn. Nó sử dụng một thuật toán sử dụng try_lock và mở khóa giúp đỡ để tránh bế tắc, trong trường hợp hai chủ đề lấy cả hai bản ghi bằng cách sử dụng cùng một chức năng. –

+0

Làm thế nào mà khác với OP chỉ tự khóa cả hai? Có thể là tôi đã đọc sai câu hỏi, nhưng tôi nghĩ rằng ông đã gợi ý rằng bằng cách có một cấu trúc khóa nhiều, bạn rõ ràng sẽ ngay lập tức tránh deadlocks như trái ngược với khóa chúng cái khác. – Puppy

+0

Không, đó là về an toàn ngoại lệ và phong cách RAII đa ổ khóa. Đọc tài liệu Boost.Thread hoặc bản thảo C++ 0x về 'lock()'. –

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