Reputation: 1372
I've got a class Tester
containing an std:thread
object, and an std::vector
of Tester
. I understand that I can't copy threads, so the push_back
is out of the question, but why emplace_back
is not working? Where is the copy in my code?
#include <iostream>
#include <thread>
#include <vector>
#include <functional>
#include <unistd.h>
class Tester
{
public:
Tester(std::function<void(void)> func) :
th(func)
{
}
~Tester()
{
th.join()
}
private:
std::thread th;
};
std::vector<Tester> testers;
void InnerHelloWorld()
{
std::cout << "Hello from the inner word!\n";
}
int main() {
std::cout << "Hello World!\n";
for(size_t i = 0 ; i < 4 ; i++)
{
testers.emplace_back(InnerHelloWorld);
}
sleep(1);
return 0;
}
Upvotes: 8
Views: 1157
Reputation: 37488
You need to define move constructor for your class so it becomes MoveInsertable and will satisfy requirements of emplace
method:
Tester(Tester && other) :
th(::std::move(other.th))
{
}
Another problem that will arise once you fix lack of move constructor is an attempt to join thread that is not nessesery joinable since actual thread could have been moved into another object. So you need to add a corresponding check:
~Tester()
{
if(th.joinable())
{
th.join();
}
}
Upvotes: 3
Reputation: 9837
Theres a couple of minor issues in your code
You missed the trailing semi-colon off of:
th.join()
But importantly, you need to give your class a move constructor - the default one is fine:
Tester(Tester&&) = default;
This is needed as when vectors resize themselves they need to move or copy their elements. A move constructor will generally be created for you but in your case having a custom destructor supresses it. See here.
This will let your code compile, but then it'll throw an exception at runtime. This is because you sometimes destruct from moved-from Testers
which will call join on a moved from thread. Fortunately this is an easy fix:
~Tester()
{
if(th.joinable())
th.join();
}
Full working code:
#include <iostream>
#include <thread>
#include <vector>
#include <functional>
#include <unistd.h>
class Tester
{
public:
Tester(std::function<void(void)> func) :
th(func)
{
}
~Tester()
{
if(th.joinable())
th.join();
}
Tester(Tester&&) = default;
private:
std::thread th;
};
std::vector<Tester> testers;
void InnerHelloWorld()
{
std::cout << "Hello from the inner word!\n";
}
int main() {
std::cout << "Hello World!\n";
for(size_t i = 0 ; i < 4 ; i++)
{
testers.emplace_back(InnerHelloWorld);
}
sleep(1);
return 0;
}
Upvotes: 16