2012-02-28 11 views
13

Hãy xem xét tôi có lamba foo mà chỉ cần làm một số công cụ và không cần phải trả lại bất cứ điều gì. Khi tôi làm điều này:std :: async sẽ không sinh ra một chủ đề mới khi giá trị trả về không được lưu trữ

std::future<T> handle = std::async(std::launch::async, foo, arg1, arg2); 

Mọi thứ đều chạy tốt và lamba sẽ được sinh ra trong một chuỗi mới. Tuy nhiên, khi tôi không lưu trữ std::future mà trả về std::async, thì foo sẽ được chạy trong chuỗi chính và chặn nó.

std::async(std::launch::async, foo, arg1, arg2); 

Tôi thiếu gì ở đây?

+5

Có lẽ '' 'future''' được trả về bởi' '' async''' bị hủy ngay lập tức. Tôi sẽ không ngạc nhiên nếu destructor của '' 'future''' có một sự chờ đợi tiềm ẩn bên trong. –

Trả lời

16

Từ just::threaddocumentation:

Nếu chính sách là std::launch::async sau đó chạy INVOKE(fff,xyz...) trên thread riêng của mình. Trả về std::future sẽ trở nên sẵn sàng khi chuỗi này hoàn tất và sẽ giữ giá trị trả lại hoặc ngoại lệ được ném bởi lời gọi hàm. Các destructor của đối tượng tương lai cuối cùng liên kết với trạng thái không đồng bộ của std::future trả về sẽ bị chặn cho đến khi tương lai đã sẵn sàng.

Trong

std::async(std::launch::async, foo, arg1, arg2); 

Tương lai trở lại không được gán bất cứ nơi nào và khối destructor của nó cho đến khi kết thúc foo.

4

Tôi muốn thêm liên kết vào bài viết của Herb Sutter trên số async and ~future trong đó ông cho rằng tương lai không bao giờ nên chặn.

+0

Nó không phải là một bài viết mà là một đề xuất. Ngoài ra, vâng, làm cho '~ future()' block là một sai lầm. – Xeo

+2

~ tương lai() không thực sự chặn theo mặc định. Nó chỉ chặn khi được trả về từ std :: async, vì async gán trạng thái chặn cho tương lai và ~ future() phải giải phóng nó. –

0

Tại sao chặn?

  1. std::async(); lợi nhuận std::futuređối tượng tạm thời
  2. tạm thời đối tượng bị phá hủy ngay lập tức, gọi desctructor.
  3. std::future destructor đang chặn. Nó là xấu và phiền hà.

Tại sao chỉ định là ok?

Bằng cách gán cho một biến, đối tượng trả về không bị hủy ngay lập tức, nhưng sau đó, cho đến khi kết thúc phạm vi mã gọi điện của bạn.

Ví dụ mã: main1 là ok. main2main3 tương đương chặn luồng chính.

void forever() { 
    while (true); 
} 

void main1() { 
    std::future<void> p = std::async(std::launch::async, forever); 
    std::cout << "printing" << std::endl; // can print, then forever blocking 
} 

void main2() { 
    std::async(std::launch::async, forever); 
    std::cout << "printing" << std::endl; // forever blocking first, cannot print 
} 

void main3() { 
    {std::future<void> p = std::async(std::launch::async, forever);} 
    std::cout << "printing" << std::endl; // forever blocking first, cannot print 
} 

Hãy xem cplusplus.com

giá trị trở lại của std :: async Khi ra mắt :: async được chọn, tương lai trả về có được liên kết với cuối chủ đề đó tạo ra, ngay cả khi trạng thái chia sẻ của nó không bao giờ được truy cập: trong trường hợp này, hàm hủy của nó đồng bộ hóa với sự trở lại của fn. Do đó, giá trị trả về sẽ không được bỏ qua đối với hành vi không đồng bộ, ngay cả khi fn trả về void.

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