Лямбда-поток C , который можно остановить извне

#c #multithreading #lambda #atomic

#c #многопоточность #лямбда #атомарный

Вопрос:

Я пытаюсь создать вспомогательный поток, который ожидает и работает / завершается, если так говорит основная команда.

Что-то вроде этого:

 std::atomic<bool> quit(false), doit(false);

std::thread([quit, doit]()
{
  while (!quit)
  {
    wait();
    if (doit)
      std::cout << "done";
  }
}
 

компилятор говорит:

 1.cpp:26:15: error: call to implicitly-del
eted copy constructor of 'atomic<bool>'
    thread t([quit, doit, ,                   ^~~~~~                      /data/data/com.termux/files/usr/include/c 
 /v1/atomic:1643:7: note: copy constructor of 'atomic<bool>' is implicitly deleted b
ecause base class '__atomic_base<bool>' has a deleted copy constructor                  : public __atomic_base<_Tp>
 

Какова цель неявного удаления и почему это имеет значение здесь?
Также: что еще я должен использовать (а не мьютекс)?

Комментарии:

1. Позвольте мне спросить вас, какой смысл копировать атомарную переменную? Если вы делите его между потоками, то создание копии не будет делиться ничем, так как каждый поток будет иметь свой собственный атомарный объект.

2. quit И doit должны быть глобальными или переменными-членами, а лямбда-выражение должно фиксировать их по ссылке.

Ответ №1:

 std::thread([quit, doit]()
 

На данный момент отложим в сторону ошибку компиляции: это говорит о том, что эта лямбда фиксирует эту doit переменную по значению. Таким образом, даже если ошибка компиляции волшебным образом исчезнет, конечным результатом будет нечто совершенно бесполезное и никогда не будет работать. Все, что будет делать лямбда, это снова и снова проверять свой захваченный doit объект, совершенно другой и независимый объект от «реального» doit объекта (потому что, в конце концов, именно так работает лямбда-захват по значению), который никто другой никогда не установит, пока время не подойдет к концу.

Если doit это глобальный объект, его не нужно захватывать. Если это не так, если он имеет локальную область видимости, лямбда-выражение должно захватить его по ссылке (используя amp; -thingy перед ним). И тогда вам нужно будет убедиться, в той или иной форме или способом, что локальная область не завершается до тех пор, пока этот поток выполнения не остановится, или, по крайней мере (каким-то образом), он больше не будет логически обращаться к захваченному по ссылке объекту, поэтому его можно уничтожить в его исходной области.