Nhận trạng thái của std :: future


82

Có thể kiểm tra xem a std::futuređã kết thúc hay chưa? Theo như tôi có thể biết cách duy nhất để làm điều đó là gọi wait_forvới thời lượng bằng 0 và kiểm tra xem trạng thái có readyhay không, nhưng có cách nào tốt hơn không?


10
@CatPlusPlus Trừ khi tôi nhầm lẫn, validchỉ kiểm tra xem tương lai có trạng thái chia sẻ hay không (tức là Nó quay trở lại truecho đến khi getđược gọi trong tương lai).
David Brown

Vì vậy, nếu getđã được gọi và trả về giá trị được lưu trữ, bạn vẫn muốn true? (Tôi không chắc chắn lý do tại sao điều này sẽ có ích, vì bạn chỉ có thể nhận được giá trị một lần.)
James McNellis

@JamesMcNell Có lẽ tôi đang hiểu nhầm hoặc sử dụng sai hợp đồng tương lai, nhưng điều tôi muốn là biết liệu chuỗi (hoặc bất cứ thứ gì đang thực hiện phép tính) đã hoàn thành hay chưa. Tương đương với Qt QFuture::isFinishedvề cơ bản.
David Brown

1
Chờ đợi với thời gian chờ bằng 0 là cách hầu hết các API trên nhiều nền tảng đối phó với một khái niệm như vậy ... Nhiều đến mức tôi sẽ coi đó là cách tiếp cận khái niệm "tiêu chuẩn". Điều này làm cho tôi một chút bối rối tại khái niệm "một cách tốt hơn" ...
asveikau

16
@asveikau Tôi không biết đây là một quy trình tiêu chuẩn. Thật kỳ lạ khi gọi một hàm chờ khi tôi không muốn đợi.
David Brown

Câu trả lời:


84

Bạn nói đúng, và ngoài việc gọi điện wait_untilbằng một thời điểm trong quá khứ (tương đương) thì không còn cách nào tốt hơn.

Bạn luôn có thể viết một trình bao bọc nhỏ nếu bạn muốn có một cú pháp thuận tiện hơn:

template<typename R>
  bool is_ready(std::future<R> const& f)
  { return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready; }

NB nếu chức năng bị hoãn lại, điều này sẽ không bao giờ trả về true, vì vậy tốt hơn là nên kiểm tra wait_fortrực tiếp trong trường hợp bạn có thể muốn chạy đồng bộ tác vụ hoãn lại sau một thời gian nhất định trôi qua hoặc khi tải hệ thống thấp.


2
wait_for không thay đổi tương lai nên tham số có thể được khai báo là const.
Jens Åkerblom

7
Trước tiên, hãy cân nhắc kiểm tra valid () để tránh lỗi thời gian chạy nếu get đã được gọi hoặc tương lai chưa bao giờ được khởi tạo.
Jeremy Sorensen

5
Wait_for (chrono :: seconds (0)) có được đảm bảo trả về ngay lập tức không hay nó có thể mang lại quyền kiểm soát luồng trong vài phần nghìn giây trên một số triển khai? Đây sẽ là khá quan trọng để biết như là một vài mili giây là rất nhiều thời gian khi mã hóa một trò chơi ...
kynnysmatto

9
@kynnysmatto, trên một số triển khai, nó có được một khóa mutex để kiểm tra trạng thái trong tương lai một cách an toàn, vì vậy nếu khóa đó bị tranh chấp (vì một chuỗi khác đang tạo trạng thái sẵn sàng hoặc cũng đang kiểm tra sự sẵn sàng) thì nó sẽ chặn và một chuỗi khác có thể chạy, nhưng khi triển khai tốt, mutex không bao giờ được giữ cho nhiều hơn một vài hướng dẫn, do đó, thậm chí không phải một phần nghìn giây. Quá trình triển khai hiện tại của GCC hoàn toàn không sử dụng mutex, nhưng cái trước đó đã làm và tạo trạng thái sẵn sàng được thực hiện bằng cách hoán đổi hai con trỏ, vì vậy mutex chỉ bị khóa rất ngắn trong khi điều đó xảy ra.
Jonathan Wakely

@JonathanWakely thử nghiệm với g ++ for(int i = 0; i < 1000; i++) f.wait_for(chrono::seconds(0));mất 43ms thời gian đồng hồ treo tường.
Daniel Kinsman

14

Có một hàm thành viên is_ready trong hoạt động cho std :: future. Trong khi đó, việc triển khai VC có một thành viên _Is_ready ().


Lưu ý rằng hàm thành viên _Is_ready () KHÔNG an toàn cho chuỗi. Nó truy cập cờ _Ready của trạng thái được liên kết theo cách không được bảo vệ. Đây ít nhất là trường hợp của VS2019 16.2.
Mattias De Charleroy

9

Đặt cược đầu tiên của tôi sẽ được gọi wait_forvới một khoảng thời gian 0, và kiểm tra mã kết quả đó có thể là một trong những future_status::ready, future_status::deferredhoặc future_status::timeout.

Trong cppreference, họ tuyên bố rằng valid() kiểm tra xem kết quả có sẵn hay không , nhưng tiêu chuẩn cho biết điều đó valid()sẽ trả về truenếu *thisđề cập đến trạng thái được chia sẻ, độc lập với việc trạng thái đó đã sẵn sàng hay chưa.


7
cppreference hiện đã được cập nhật và cho biết "kiểm tra xem tương lai có trạng thái được chia sẻ hay không". (Không chắc bạn muốn xóa đoạn thứ hai của mình hay chỉnh sửa nó, vì vậy tôi sẽ không tự sửa đổi).
Mặc định
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.