У меня есть поток, который я хочу сидеть в цикле, пока я не буду готов выйти из программы, и в этот момент я хочу, чтобы он вышел из цикла и вышел, чтобы я мог вызвать std::thread::join
в теме. Во времена c ++ 03 я просто использовал bool, защищенный блокировкой, чтобы сообщить потоку, когда выходить. На этот раз я подумал, что воспользуюсь новой библиотекой атомистики (особенно std::atomic_bool
), но у меня проблемы. Ниже мой тестовый пример:
#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;
}
Декларация thread t
выплевывает этот чудовище, когда я пытаюсь скомпилировать. Центральная часть ошибки выглядит так:
неверная инициализация неконстантной ссылки типа ‘std :: atomic_bool&Из значения типа ‘std :: atomic_bool’
Почему я не могу получить ссылку на atomic_bool
? Что мне делать вместо этого?
Вы должны явно передать ссылку на ваш поток. С помощью std::ref
создаст std::reference_wrapper
который может быть скопирован и будет содержать ссылку на вашу функцию.
thread t(setBool, std::ref(b));
В противном случае он попытается скопировать ваш атомарный, что невозможно скопировать.
Как объяснил Бэмбун, вы должны обернуть объекты std::ref
если вы действительно хотите, чтобы они передавались по ссылке через std::thread
конструктор переменных-аргументов. (То же самое относится к std::async
.) Чтобы избежать этого нелогичного поведения, вы можете использовать лямбду, которая ведет себя именно так, как вы ожидаете. Просто используйте это, чтобы создать тему:
thread t([&]{ setBool(b); });
С лямбдами нет необходимости в бессмысленной реф / креф, когда вы хотите передать аргументы по ссылке.
Я только что столкнулся с этим, я думаю, что вы также можете решить свою проблему, передавая адрес атомарному так:
std::atomic<bool> b{false};
std::thread t(setBool, &b);
Где ваша функция берет указатель на атомарный:
void setBool(std::atomic<bool>* ab)
Я не уверен, какова принятая практика, я полагаю, что вы могли бы передать нулевой указатель на атомарный путь таким образом, но я не уверен, почему вы захотите.