Использование атомики с std :: thread в c ++ 11

У меня есть поток, который я хочу сидеть в цикле, пока я не буду готов выйти из программы, и в этот момент я хочу, чтобы он вышел из цикла и вышел, чтобы я мог вызвать 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? Что мне делать вместо этого?

7

Решение

Вы должны явно передать ссылку на ваш поток. С помощью std::ref создаст std::reference_wrapper который может быть скопирован и будет содержать ссылку на вашу функцию.

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

В противном случае он попытается скопировать ваш атомарный, что невозможно скопировать.

13

Другие решения

Как объяснил Бэмбун, вы должны обернуть объекты std::ref если вы действительно хотите, чтобы они передавались по ссылке через std::threadконструктор переменных-аргументов. (То же самое относится к std::async.) Чтобы избежать этого нелогичного поведения, вы можете использовать лямбду, которая ведет себя именно так, как вы ожидаете. Просто используйте это, чтобы создать тему:

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

С лямбдами нет необходимости в бессмысленной реф / креф, когда вы хотите передать аргументы по ссылке.

4

Я только что столкнулся с этим, я думаю, что вы также можете решить свою проблему, передавая адрес атомарному так:

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

Где ваша функция берет указатель на атомарный:

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

Я не уверен, какова принятая практика, я полагаю, что вы могли бы передать нулевой указатель на атомарный путь таким образом, но я не уверен, почему вы захотите.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector