Ответ 1
Вы можете сделать это следующим образом:
std::thread(Foo).detach();
Рассмотрим следующую короткую программу:
#include <thread>
int Foo() {
while (1);
}
int main(){
std::thread t(Foo);
std::thread s(Foo);
// (std::thread(Foo));
t.join();
}
Это компилируется и запускается (навсегда), с
g++ -Wl,--no-as-needed DoubleBufferTest.cc -o DoubleBufferTest -std=c++0x -pthread
В прокомментированной строке я пытаюсь использовать описанную здесь технику, чтобы анонимно анонсировать новую тему. Однако, когда эта строка будет прокомментирована, я могу скомпилировать, но запуск дает следующую ошибку:
terminate called without an active exception
Aborted (core dumped)
Как я могу анонимно объявить поток?
Заметьте, я на g++ 4.4.7
.
Вы можете сделать это следующим образом:
std::thread(Foo).detach();
std::thread
destructor вызовет std::terminate
если поток не был соединен или отсоединен.
Поэтому, к сожалению, вы не можете создать анонимный объект потока, например: вам нужна ссылка на объект thread
, чтобы вызвать либо join()
либо detach()
.
Скотт Мейерс рассказал о Going Native 2013, где он создал класс RAII, который обертывает поток и вызывает соединение в деструкторе. Вы можете сделать что-то подобное:
class ThreadRAII {
public:
ThreadRAII(std::thread&& thread): t(std::move(thread)) {}
~ThreadRAII() { if (t.joinable()) { t.join(); }
private:
std::thread t;
};
См. Его сообщение в блоге или беседу для получения дополнительной информации.
Вы можете использовать его так
(ThreadRAII(std::thread(Foo)));
Однако единственной причиной, по которой вы хотите создать поток таким образом, является то, что вам все равно, когда (или если) оно закончится, поэтому в этом случае объединение не имеет большого смысла. Вместо этого вы должны изменить деструктор, чтобы отсоединить:
~ThreadRAII() { if (t.joinable()) { t.detach(); }
Как было предложено в комментариях, вы могли бы сделать его еще проще в использовании, совершенствуя пересылку во внутреннюю резьбу при строительстве:
class ThreadRAII2 {
public:
template <typename Func, typename ...Args>
explicit ThreadRAII2(Func&& func, Args&&... args) :
t(func, std::forward<Args>(args)...) { }
~ThreadRAII2() {
if (t.joinable()) t.detach();
}
private:
std::thread t;
};
Тогда вы можете использовать его так же, как вы изначально хотели, без необходимости отсоединения:
(ThreadRAII2(Foo));
Или, если Foo
принимает аргументы (например, Foo(int)
):
(ThreadRAII2(Foo, 42));
Я не думаю, что это (техника, о которой вы говорите) возможно с помощью потоков.
Взгляните сюда;
30.3.1.3 thread destructor [thread.thread.destr]
~ Нить();
Если joinable(), то terminate(), иначе никаких эффектов. [Примечание. Либо неявное разделение или объединение потока joinable() в его деструкторе может привести к ошибкам отладки (для отсоединения) или производительности (для объединения), возникающим только при возникновении исключения. Таким образом, программист должен убедиться, что деструктор никогда не выполняется, пока поток все еще соединен. - конечная нота]
В основном создаваемый вами временный анонимный объект (т.е. поток) разрушается, когда выполнение продолжается до следующей строки, которая нарушает вышеуказанное правило.