Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vector of std::threads

C++11

I am trying to make a vector of std::threads. The combination of the following three points says I can.

1.) According to http://en.cppreference.com/w/cpp/thread/thread/thread, thread’s default constructor creates a

thread object which does not represent a thread.

2.) According to http://en.cppreference.com/w/cpp/thread/thread/operator%3D, thread’s operator=

Assigns the state of [the parameter, which is a thread rvalue reference] to [the calling thread] using move semantics.

3.) According to http://en.cppreference.com/w/cpp/container/vector/vector, passing only a size type variable to a vector constructor will construct

the container with [the specified number of] value-initialized (default constructed, for classes) instances of T. No copies are made.

So, I did this:

#include <iostream>
#include <thread>
#include <vector>

void foo()
{
    std::cout << "Hello\n";
    return;
}

int main()
{
    std::vector<std::thread> vecThread(1);
    vecThread.at(0) = std::thread(foo);
    vecThread.at(0).join();
    return 0;
}

This runs as expected in VC11 and g++ 4.8.0 (online compiler here) as seen in the following:

Console Output:

Hello

Then I tried it in clang 3.2, by toggling the compiler menu on the same webpage, which gives:

stderr: 
pure virtual method called
terminate called without an active exception

When a thread object—that represents a thread—goes out of scope before being join()ed or detach()ed, the program will be forced to terminate. I have join()ed vecThread.at(0), so the only thing left in question is the temporary thread

std::thread(foo);

in the

vecThread.at(0) = std::thread(foo);

assignment.

However, according to the web reference, threads can only be assigned by moving a thread rvalue reference. I cannot think of any way to join() or detach() a temporary thread object.

So if clang’s output is correct, then what is the use of thread’s operator=? Or is this a clang compiler bug?

In g++ 4.8.0, changing the line

vecThread.at(0) = std::thread(foo)

to

vecThread.at(0) = std::thread{foo}

(replacing parentheses with braces) still gives the expected Hello output.

However, changing the line to vecThread.at(0) = {foo} makes it complain:

g++ 4.8.0's complaint on braces:

error: converting to 'std::thread' from initializer list would use explicit constructor 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(); _Args = {}]' vecThread.at(0) = {foo};

which is too advanced—I don’t know what it means.

Making the same change in clang gives the even more advanced:

clang 3.2's complaint on braces:

error: no viable overloaded '='
vecThread.at(0) = {foo};
...
note: candidate function not viable: cannot convert initializer list
argument to 'const std::thread'
thread& operator=(const thread&) = delete;
...
note: candidate function not viable: cannot convert initializer list
argument to 'std::thread'
thread& operator=(thread&& __t) noexcept

and I don’t know what that means either.

I cannot use VC11 to corroborate the above

vecThread.at(0) = {foo}

problems because VC11, as of the November 2012 CTP compiler, does not support uniform initialization syntax on the Standard Library.

like image 437
CodeBricks Avatar asked Mar 16 '13 03:03

CodeBricks


People also ask

How do you create a vector thread in C++?

Changing contents of vector of thread vecOfThreads[1] = std::move(th4); //Destructor of already existing thread object will call terminate vecOfThreads[1] = std::move(th4); //Destructor of already existing thread object will call terminate vecOfThreads[1] = std::move(th4);

What is an std::vector?

1) std::vector is a sequence container that encapsulates dynamic size arrays. 2) std::pmr::vector is an alias template that uses a polymorphic allocator. The elements are stored contiguously, which means that elements can be accessed not only through iterators, but also using offsets to regular pointers to elements.

Is Vector thread safe in C++?

The C++11 standard does not expect to be able to safely call non const functions simultaneously. Therefore all classes available from the standard, e.g. std::vector<>, can safely be accessed from multiple threads in the same manner.

Is std :: thread copyable?

std::thread::operator= thread objects cannot be copied (2).


1 Answers

Your first example is correct. Throwing an exception is a known bug, when you using clang with libstdc++. To solve it, you have to install libc++(llvm version of c++ library). See an example of compiling with libc++ below

#include <thread>

int main()
{
    std::thread t([] () {});
    t.join();
    return 0;
}

$ clang++ -std=c++11 -stdlib=libc++ main.cpp -o main -lc++ -lsupc++ -lpthread

P.S. See here, why is the flag -lsupc++ required too.

like image 148
awesoon Avatar answered Nov 05 '22 12:11

awesoon