How do I allow a C ++ 11 thread to perform several different functions?
I am learning new multithreading techniques in C ++ 11. Almost all tutorials I read on the internet describe how to start a new thread (or multiple threads) executing a function, how to attach (or detach) a thread (or threads) later, and how to avoid racing conditions with help mutex
etc.
But I don't see any of them showing how to get a thread to do multiple functions in different parts of the program. The question is, with C ++ 11 streams, is it possible to achieve the following? If so, how? (An example would be great.)
void func1(std::vector<int> & data1){ ... }
void func2(std::vector<int> & data2){ ... }
// main function version I
int main(){
std::vector<int> data1;
// prepare data1 for func1;
std::thread t1(func1, std::ref(data1));
std::vector<int> data2;
// prepare data2 for func2;
if (func1 in t1 is done){
t1(func2, std::ref(data2));
}
t1.join();
return 0;
}
And further, what if I want to put the specified body main
in a loop like below. Is it possible? If so, how?
//main function version II
int main(){
std::vector<int> bigdata1;
std::vector<int> bigdata2;
std::thread t1; // Can I do this without telling t1 the function
// to be executed?
for(int i=0; i<10; ++i){
// main thread prepare small chunk smalldata1 from bigdata1 for func1;
if(t1 is ready to execute a function){t1(func1, std::ref(smalldata1));}
// main thread do other stuff, and prepare small chunk smalldata2 from bigdata2 for func2;
if (func1 in t1 is done){
t1(func2, std::ref(smalldata2));
}
}
t1.join();
return 0;
}
source to share
Link from cplusplus.com :
the default constructor creates a thread object that does not represent any thread of execution.
Therefore, it std::thread t
simply does not define the executable thread. When creating a thread, the thread function must be provided and it cannot be installed later.
For your main version of function I, you will need to create two threads. Something like the following:
int main(){
std::vector<int> data1;
// prepare data1 for func1;
std::thread t1(func1, std::ref(data1));
std::vector<int> data2;
// prepare data2 for func2;
t1.join(); // this is how you wait till func1 is done
// you will have to create a new thread here for func2
std::thread t2(func2, std::ref(data2));
t2.join(); // wait for thread2 (func2) to end
return 0;
}
Likewise, you can put them in a loop, which is fine, which will give you the main version II function.
source to share
C ++ 11 threading are primitives designed to enable you to write real libraries. They are not easy to use. You have to wrap them up.
Something like:
struct tasks {
std::mutex m;
std::condition_variable v;
std::vector<std::packaged_task<void>> work;
std::vector<std::future<void>> finished;
void operator()(){
while(true){
std::packaged_task<void> f;
{
std::unique_lock<std::mutex> l(m);
if (work.empty()){
v.wait(l,[&]{return !work.empty();});
}
f = std::move(work.front());
work.pop_front();
}
if (!f.valid()) return;
f();
}
}
std::future<void> do(std::function<void()> f){
std::packaged_task<void> p(f);
auto r=p.get_future();
{
std::unique_lock<std::mutex> l(m);
work.push_back(std::move(p));
v.notify_one();
}
return r;
}
void start(){
finished.push_back(std::async(std::launch_policy::async,
std::ref(*this)));
}
~tasks(){
std::unique_lock<std::mutex> l(m);
for(auto&&unused:finished){
work.push_back({});
}
v.notify_all();
}
};
usage looks like this:
int main(){
tasks t;
t.start();
t.do([]({std::cout<<"hello ";});
t.do([]({std::cout<<"world\n";});
}
if you want to know when the task is done, check that the future will be returned do
.
Written on the phone, not compiled, possibly filled with typos and errors, but a place to start.
Doesn't support early cancellation. Easy to write abaondon
, which is devastating work
.
Supports multiple consumers (workwe threads) which I suspect. On a compatible system, dtor will wait for all threads to finish jobs in the queue. Not on MSVC2013 tho.
source to share