2012-10-27 42 views
7

Tôi có một chuỗi mà tôi muốn ngồi trong vòng lặp cho đến khi tôi sẵn sàng thoát khỏi chương trình, tại thời điểm đó tôi muốn nó thoát ra khỏi vòng lặp và thoát ra để tôi có thể gọi số std::thread::join trên đó. Trong những ngày của c + + 03, tôi sẽ chỉ sử dụng một bool được bảo vệ bởi một khóa để cho biết thread khi để thoát. Lần này tôi nghĩ rằng tôi sẽ tận dụng lợi thế của thư viện nguyên tử mới (cụ thể là std::atomic_bool), nhưng tôi đang gặp rắc rối. Dưới đây là trường hợp thử nghiệm của tôi:Sử dụng nguyên tử với std :: thread in C++ 11

#include <atomic> 
#include <thread> 
#include <cstdio> 

using namespace std; 

void setBool(atomic_bool& ab) 
{ 
    ab = true; 
} 

int main() 
{ 
    atomic_bool b; 
    b = false; 
    thread t(setBool, b); 
    t.join(); 
    printf("Atomic bool value: %d\n", b.load()); 
    return 0; 
} 

Tờ khai thread t spits ra this quái khi tôi cố gắng để biên dịch. Phần trung tâm của lỗi có vẻ là:

khởi không hợp lệ tham chiếu không const kiểu 'std :: atomic_bool &' từ một rvalue của loại 'std :: atomic_bool'

Tại sao sao tôi không thể tham chiếu đến một số atomic_bool? Tôi nên làm gì?

+0

@NicolBolas Làm thế nào? Không phải là khóa một biến với một mutex trước khi truy cập nó một cách tiêu chuẩn để chia sẻ dữ liệu giữa các chủ đề? –

+0

Ồ, đúng vậy. Nevermind ... –

Trả lời

13

Bạn phải chuyển rõ ràng một tham chiếu đến chuỗi của mình. Sử dụng std::ref sẽ tạo một std::reference_wrapper có thể sao chép được và sẽ mang hàm ref đến chức năng của bạn.

thread t(setBool, std::ref(b)); 

Nếu không, nó sẽ cố gắng sao chép nguyên tử của bạn, không thể đọc được.

+0

Tại sao lại cố gắng sao chép? Không đưa ra tên biến cho đối số tham chiếu truyền thống biến đó theo tham chiếu? –

+4

@ slavik262 có, điều đó đúng. Trình xây dựng thread thực hiện điều đó, khi bạn gọi một hàm mà bạn không biết khi nào nó sẽ thực hiện, nếu bạn chuyển một tham chiếu, tham chiếu có thể không hợp lệ, do đó nó sẽ sao chép các đối số của bạn để lưu chúng một cách an toàn. Nếu bạn sử dụng một trình bao bọc (ref-wrapper) một cách rõ ràng, đó là công việc của bạn để đảm bảo rằng đối tượng sẽ tồn tại chủ đề. – inf

+0

Cảm ơn bạn đã giải thích! –

4

Khi bamboon giải thích, bạn phải bọc các đối tượng với std::ref nếu bạn thực sự muốn chúng được chuyển bằng tham chiếu qua hàm tạo đối số biến của std::thread. (Điều này cũng áp dụng cho std::async.) Để tránh hành vi phản trực giác này, bạn có thể sử dụng lambda, hoạt động chính xác như bạn mong đợi. Chỉ cần sử dụng điều này để tạo chủ đề:

thread t([&]{ setBool(b); }); 

Với lambdas, không cần phải có ref/cref vô nghĩa khi bạn muốn chuyển đối số bằng tham chiếu.

+0

Cảm ơn!Tôi biết rõ về lambdas (chúng tuyệt vời) - Tôi chỉ muốn giảm thiểu lượng ma thuật C++ 11 mà tôi đã sử dụng cho trường hợp thử nghiệm của mình để cô lập vấn đề. –

0

Tôi chỉ cần chạy vào này là tốt, tôi nghĩ rằng bạn cũng có thể giải quyết vấn đề của bạn bằng cách thông qua một địa chỉ để các nguyên tử như vậy:

std::atomic<bool> b{false}; 
std::thread t(setBool, &b); 

đâu chức năng của bạn mất một con trỏ đến các nguyên tử:

void setBool(std::atomic<bool>* ab) 

Tôi không chắc thực hành được chấp nhận là gì, tôi cho rằng bạn có thể chuyển một con trỏ rỗng tới nguyên tử theo cách này nhưng tôi không chắc chắn tại sao bạn muốn.

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