5

Spurious wakup được nhiều nền tảng cho phép. Để chống lại điều đó, chúng tôi viết cơ chế lặp bên dưới:Điều kiện condition_variable :: wait_for() đối phó với các lần đánh thức giả mạo như thế nào?

while(ContinueWaiting()) 
    cv.wait(lock); // cv is a `std::conditional_variable` object 

Điều tương tự cũng dễ hiểu đối với conditional_variable::wait_until().
Nhưng nhìn vào bên dưới Ví dụ:

const auto duration = Returns_10_seconds(); 
while(!Predicate()) 
    cv.wait_for(lock, duration); 

Hãy tưởng tượng rằng, wakeup giả xảy ra tại 1 giây. Thời gian chờ chưa đạt đến.
Nó có chờ thêm 10 giây nữa không? Điều này sẽ dẫn đến vòng lặp vô hạn, mà tôi chắc chắn không nên xảy ra. Từ mã nguồn, nội bộ wait_for() gọi wait_until().

Tôi muốn hiểu, làm cách nào để wait_for() xử lý các lần đánh thức giả mạo?

+2

Nó không. Bạn phải tự mình kiểm tra hoặc sử dụng tình trạng quá tải thực hiện nó cho bạn (một trong đó có một vị từ). –

+0

@MaiLongdong, biến vị ngữ chỉ được sử dụng để chống lại các lần đánh thức như vậy. Ngay cả 'wait_for()' nếu nó hoạt động tốt trong nền tảng của tôi, không đảm bảo rằng nó sẽ hoạt động ở khắp mọi nơi, bởi vì wakesups giả là nền tảng phụ thuộc. – iammilind

+1

Nếu bạn không muốn 'wait_for' 10 giây sử dụng' wait_until' 'now()' + 10 giây :-) –

Trả lời

4

Tôi muốn hiểu, làm thế nào wait_for() giao dịch với đánh thức giả mạo?

Không.

Chức năng này thường được sử dụng trong trường hợp nếu bạn thức dậy một cách giả mạo, bạn vẫn muốn thực hiện một số công việc khác. Và nếu bạn không thức dậy một cách giả mạo, bạn muốn ép buộc một "giả mạo" thức dậy vào thời điểm duration đã trôi qua. Điều này có nghĩa là nó không thường được sử dụng trong một vòng lặp như bạn hiển thị, cho chính xác những lý do bạn nhà nước. I E. thời gian chờ và các lần đánh thức giả mạo được xử lý giống hệt nhau.

Bây giờ bạn có thể tự hỏi, vâng, phiên bản biến vị ngữ làm gì, vì nó ngụ ý một vòng lặp?

template <class Rep, class Period, class Predicate> 
bool 
wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time, 
     Predicate pred); 

này được quy định để có hiệu ứng giống như:

return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred)); 

Các wait_until biến không phân biệt giữa ups trỗi dậy giả mạo và timeout. Làm như vậy với một vòng lặp như sau:

while (!pred()) 
    if (wait_until(lock, abs_time) == cv_status::timeout) 
     return pred(); 
return true; 
2

Đây là những gì tiêu chuẩn đã nói về wakeups giả mạo:

30,5 biến Điều kiện [thread.condition]

biến Điều kiện cung cấp nguyên thủy đồng bộ sử dụng để ngăn chặn một sợi cho đến khi thông báo bằng một số khác chủ đề rằng một số điều kiện được đáp ứng hoặc cho đến khi đạt đến thời gian hệ thống.

...

10 Lưu ý: Đó là trách nhiệm của người sử dụng để đảm bảo rằng đề chờ đợi không sai lầm cho rằng các chủ đề đã kết thúc nếu họ kinh nghiệm wakeups giả mạo.

Từ từ ngữ có vẻ khá rõ ràng rằng trách nhiệm đối phó với các lần đánh thức giả mạo là trên người dùng.

1

            
 
  
              
    const auto duration = Returns_10_seconds(); 
    while(cv.wait_for(lock, duration) == std::cv_status::timeout); 

            
 

này chắc chắn là một điều sai lầm khi làm và do đó không có ý nghĩa thảo luận làm thế nào để sửa chữa nó đối với trường hợp wakeups giả mạo, vì nó được chia ngay cả đối với trường hợp của wakeups bình thường, bởi vì điều kiện chờ đợi không được kiểm tra lại sau khi trở về từ sự chờ đợi.

const auto duration = Returns_10_seconds(); 
while(!Predicate()) 
    cv.wait_for(lock, duration); 

Ngay cả sau khi chỉnh sửa, câu trả lời vẫn như cũ: bạn có thể không thực sự xử lý "wakeups giả mạo", bởi vì bạn có thể không thực sự biết lý do cho wakeup - nó cũng có thể là một hoàn toàn đánh thức hợp pháp do một cuộc gọi đến condition_variable::notifyXXX trước khi hết thời gian chờ.

Trước tiên, lưu ý rằng bạn không thể phân biệt được giữa một lần đánh thức gây ra bởi một cuộc gọi đến condition_variable::notifyXXX và báo thức gây ra bởi, ví dụ như tín hiệu POSIX [1]. Thứ hai, ngay cả khi tín hiệu POSIX không quan tâm, chủ đề chờ vẫn phải xem xét lại điều kiện vì điều kiện có thể thay đổi giữa thời gian biến điều kiện được báo hiệu và chuỗi chờ trả về từ điều kiện chờ.

Điều bạn thực sự phải làm là xử lý theo cách đặc biệt không thức dậy trước thời gian chờ, nhưng thức dậy do hết giờ.Và điều đó hoàn toàn phụ thuộc vào lý do có thời gian chờ ở vị trí đầu tiên, tức là về chi tiết của miền ứng dụng/vấn đề.

[1] nếu chờ đợi vào một biến tình trạng bị gián đoạn bởi một tín hiệu, sau khi thực hiện xử lý tín hiệu thread được phép hoặc tiếp tục chờ đợi hoặc trả lại

+0

Đoạn 1 của bạn là đúng, thực sự tôi đã viết nó theo cách hiện tại khi tôi đăng. Sau đó, tôi thay đổi nó thành những gì có [cplusplus.com] (http://www.cplusplus.com/reference/condition_variable/condition_variable/wait_for/). Bạn có thể chỉnh sửa câu trả lời theo trạng thái hiện tại của câu hỏi. – iammilind

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