2013-03-17 35 views
6
std::promise<int> p1; 
auto f = p1.get_future(); 

{ 
    std::promise<int> p2(std::move(pr)); 
} 

bool valid = f.valid(); // true 
f.wait(); // does not throw, or fail, but returns immediately 
f.get(); // throws an exception 

Có cách nào để kiểm tra xem tương lai có sắp bị ném trước khi gọi get không? Tôi hy vọng valid sẽ kiểm tra ... Tôi không thực sự chắc chắn làm thế nào để có được valid để trả về false. Phá hủy các promise mà không cần thiết lập một giá trị không làm điều đó.tương lai, lời hứa và ngoại lệ

+2

Một 'std :: future' có thể được xem như một người quan sát đến trạng thái của' std :: promise'. Nếu lời hứa đã biến mất, tương lai sẽ lơ lửng. Nó không phải UB như sehe nói, nhưng bạn nhận được một ngoại lệ 'std :: broken_promise', bởi vì lời hứa không bao giờ có thể được lấp đầy. – Xeo

+0

hợp lệ sẽ trả về false khi bạn đã gọi 'get' hoặc' share' một lần. – inf

+1

[tương lai :: hợp lệ] (http://en.cppreference.com/w/cpp/thread/future/valid) nói 'Kiểm tra xem tương lai có đề cập đến trạng thái chia sẻ' hay không. Nếu lời hứa đã biến mất và giá trị chưa bao giờ được đặt không có nghĩa là không có trạng thái chia sẻ? – David

Trả lời

5

Có cách nào để kiểm tra xem một tương lai sắp xảy ra trước khi gọi có được không?

Không, bằng cách nào đó bằng cách nào đó sẽ nhận được giá trị được lưu trữ trong tương lai.

Tôi hy vọng hợp lệ sẽ kiểm tra ... Tôi không thực sự chắc chắn cách hợp lệ để trả về false.

trị trả về true nếu tương lai dùng để chỉ một trạng thái chia sẻ mà chỉ có thể được tạo ra bởi std::async, std::packaged_task hoặc std::promise. Một ví dụ sẽ là mặc định được xây dựng std::future. Có giá trị cũng sẽ sai khi bạn đã gọi get hoặc share trên tương lai hợp lệ (hợp lệ == đúng) một lần.
Gọi bất kỳ chức năng nào khác ngoài valid hoặc toán tử chuyển-chuyển vào tương lai không hợp lệ (hợp lệ == false) là UB.

Phá hủy lời hứa mà không đặt giá trị sẽ không thực hiện.

Không, như đã đề cập ở trên không phải là điểm hợp lệ, vì tương lai vẫn đề cập đến trạng thái chia sẻ chỉ ở phía bên kia - lời hứa - không được đáp ứng. Nếu hủy bỏ một lời hứa không có giá trị hoặc ngoại lệ được thiết lập, một ngoại lệ để chỉ ra lời hứa bị hỏng được thiết lập.

1

Có cách nào để kiểm tra xem một tương lai có sắp xảy ra trước khi gọi không?

Câu hỏi của bạn là tương đương với:
Có cách nào để kiểm tra xem một hàm sẽ ném trước khi gọi nó?

Câu trả lời cho cả hai câu hỏi, nói chung là không.

xem xét:

int func_that_might_throw() 
{ 
    if (rand() % 2) 
    throw 1; 
    return 0; 
} 

std::future<int> f = std::async(&func_that_might_throw); 

int result = f.get(); 

Cuộc gọi async có thể trở lại một chức năng thu nhập hoãn lại, trong trường hợp chức năng thậm chí không chạy cho đến khi bạn gọi get(), vì vậy nói chung không có cách nào để biết trước liệu kết quả sẽ là một giá trị hoặc một ngoại lệ. (Bạn có thể phát hiện hàm bị trì hoãn bằng cách gọi f.wait_for(std::chrono::seconds(0)), nhưng async có thể không trả về hàm bị trì hoãn và trong trường hợp đó hàm vẫn có thể chạy không đồng bộ khi bạn thử kiểm tra xem nó có ngoại lệ được lưu trữ hay không, vì vậy bạn phải kiểm tra nếu nó đã sẵn sàng và có ngoại lệ được lưu trữ, do đó việc kiểm tra chỉ trở nên rất lộn xộn.)

Một trạng thái được chia sẻ hợp lệ sẵn sàng có kết quả là giá trị hoặc ngoại lệ. Cả hai đều là kết quả hợp lệ.Nếu bạn không muốn xử lý các ngoại lệ thì bạn nên đảm bảo một ngoại lệ không được đặt trong trạng thái được chia sẻ ở địa điểm đầu tiên.

+0

Trong tương lai :: không cần phải có thứ gì đó giống như 'if (IsReady()) trả về giá trị; nếu (! PromiseExists()) ném vỡ: lời hứa; '? Do đó có thể có một hàm trả về '! IsReady() &&! PromiseExists()'. Tôi không thực sự hiểu tại sao trường hợp này không phù hợp để không hợp lệ (... 'valid() == false') nhưng các nhà thiết kế đã không làm điều đó. – David

+0

Để nói ngắn gọn về trường hợp sử dụng của tôi: Tôi khởi động một loạt các tác vụ không đồng bộ (sử dụng hàng đợi async của riêng tôi, không phải std :: async) mỗi khung (~ 20). Khung tiếp theo tôi muốn hủy bỏ bất kỳ tác vụ nào chưa thực thi và đẩy một nhóm mới 20 để có khả năng được thực thi. Tôi muốn hàng đợi không đồng bộ của tôi trả lại cho tôi một tương lai khi tôi đẩy một công việc vào nó, nhưng nếu tôi không thể nói rằng công việc đã bị hủy bỏ hay không bằng cách sử dụng tương lai tôi không thể sử dụng tương lai, hoặc tôi sẽ phải quấn chúng lại. Tôi có thể làm điều đó bằng cách gọi và bắt được ngoại lệ, nhưng điều đó quá chậm. – David

+0

Để bình luận đầu tiên của bạn: 'broken_promise' được thiết lập khi lời hứa biến mất, không phải khi bạn tìm kiếm kết quả. 'valid()' có nghĩa là "đã chia sẻ trạng thái" và tương lai vẫn có trạng thái chia sẻ, như đã được nói nhiều lần bây giờ. –

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