Associate packaged_task and thread in C++ - c++

all
I have a class:
class someClass
{
public:
vector<int> someOperation(int start, int end)
{
// do something...
}
}
and a main function:
int main()
{
someClass obj;
std::packaged_task<vector<int>(int, int)> task(&someClass::someOperation);
std::thread t1 = std::thread(std::move(task), &obj, 0, 200); // Error happens here
std::thread t2 = std::thread(std::move(task), &obj, 201, 400);
std::thread t3 = std::thread(std::move(task), &obj, 401, 600);
t1.join();
t2.join();
t3.join();
return 0;
}
I expect this code can create three threads that run same operation on different part of a piece of data. However, in the definition of thread t1, compiler pops following error:
error C2046: term does not evaluate to a function taking 3 arguments
May I know what am I wrong, and how can I do it right?
Many thanks in advance.
Long

The problem is that &someClass::someOperation cannot be used without an instance of someClass. You realise that because you do pass one such instance into the thread constructor, but forgot it in the packaged_task signature:
std::packaged_task<vector<int>(someClass*, int, int)> task(&someClass::someOperation);
Another issue is that you are trying to move task into three different places. That won't work: after it moves once, the task won't be valid anymore, and moving it into the other threads won't do what you expect. You need three different tasks.

Related

Allow only certain threads to execute in parallel

I got two member functions for a class, say foo1 and foo2.
foo1 receives a string label and a data as inputs and calls foo2.
class MyClass {
public:
void foo1(int data, std::string label) {
// do stuff
foo2();
}
void foo2(void) {}
};
Now, I want to be able to create threads for parallel executions of foo1, but only threads of different labels can execute in parallel.
If a thread of labelA is called and another thread of the same label is still running, the first thread has to wait for the second thread to end its execution.
// t1 and t2 should run in parallel, t3 should wait for t1 to end
std::thread t1(foo1, "LabelA", 5);
std::thread t2(foo1, "LabelB", 8);
std::thread t3(foo1, "LabelA", 1);
Is this a known concurrency problem? I coudn't find a way to approach this problem, as it seems that a mutex is not enough in this case.
In summary, my question is: how to allow only certain "types of threads" to execute in parallel?
A mutex is exactly what you want. You just need 1 mutex per label, for instance in a std::map keyed by label. Then, foo1() can lock the std::mutex of the specified label, and unlock it when finished, eg:
std::map<std::string, std::mutex> locks;
class MyClass {
public:
void foo1(int data, std::string label)
{
std::lock_guard<std::mutex> g(locks[label]);
// do stuff
foo2();
}
void foo2()
{
...
}
};
// only one these "LabelA" threads should run in parallel with "LabelB" thread,
// the other "LabelA" thread should wait for the earlier "LabelA" thread to end
locks["LabelA"];
locks["LabelB"];
std::thread t1(&MyClass::foo1, &SomeMyClassObj, 5, "LabelA");
std::thread t2(&MyClass::foo1, &SomeMyClassObj, 8, "LabelB");
std::thread t3(&MyClass::foo1, &SomeMyClassObj, 1, "LabelA");
...
Demo

How to process instances of classes in parallel in C++?

I have a variable number of instances of one class, normally 3. I would like to call the class functions in each iteration of an infinite loop. Currently it is working sequentially, meaning I call each member function after each other. I would like to parallelize that part. What do you recommend?
I tried to construct an std::vector<std::thread>. I could initialize the threads and call a function on them at initialization.
MyCustomClass my_class_instance();
std::thread one_thread(&MyCustomClass::init, &my_class_instance, "string");
threads_.push_back(std::move(one_thread));
But now I would like to get each thread of the vector threads and then to call the class member function. If it would be a std::vector of class instances I would just call: vector.at(index).class_function(). How do I do that for threads? Or is that not possible?
By the way, it is in C++.
Thanks
In c++11, speciy std::launch::async is one of your choice, if asynchronicity is essential for you.
There are two launch policy:
std::launch::async, means that the function must be run asynchronously, i.e, on a different thread.
std::launch::deferred, means that the function may run only when get or wait is called on the future return by std::async. When get or wait is invoked, the function will execute synchronously. The caller of the function will be blocks until the fucntion finish running. If get or wait
is not invoked, then the function will never run.
auto future1 = std::async(my_function); // run my_function using defautl launch policy
auto future2 = std::async(std::launch::async | std::launch::deferred) // run my_function either async or defered
Refered from the book "Effective Modern C++" by Scoot Meyers, item 36: Specify std::launch ::async if asynchronicity is essential.
If parallel computing is what you need, you may consider using OpenMP.
Reference: https://en.cppreference.com/w/cpp/thread/async
This code maybe help you.
class test_thread_instanse
{
public:
void operator()(int x)
{
std::cout << "test" <<x << std::endl;
}
};
int main()
{
std::thread t1(test_thread_instanse(), 1);
std::thread t2(test_thread_instanse(), 2);
std::thread t3(test_thread_instanse(), 3);
t1.join();
t2.join();
t3.join();
return(0);
}

Is there a way to create a thread but defer it's execution using C++11 without using the operator=

two threads are created if i use the following:
void func()
{}
std::thread td1;//thread object created.
...
...
//defer the running of td1 until now
td1 = std::thread(func);//temp thread object(rvalue) created
Is there a way to achieve the defer execution but without creating two threads?
I'm not sure what the point is, but...
No operator=, though two threads are constructed:
std::thread td1;
...
std::thread(func).swap(td1);
Or no operator= and only one thread constructed:
std::promise<void> p;
std::thread td1([&]() {
p.get_future().wait();
func();
});
...
p.set_value();
td1.join(); // Can't let p go out of scope pending the thread.
Maybe what you really want is:
std::unique_ptr<std::thread> td1;
...
td1.reset(new std::thread(func));
std::thread td1;
That creates a thread object, but it does not create a thread. So:
std::thread td1;
td1 = std::thread(func);
is perfectly fine code even if you are concerned about performance.

passing multiple arguments to a threaded function from another class

Say I have a class:
class This
{
void that(int a, int b);
};
and in my main function I need to start 'that' in a thread, and pass it 2 arguments.
This is what I have:
void main()
{
This t;
t.that(1,2); //works unthreaded.
std::thread test(t.that(1,2)); // Does not compile. 'evaluates to a function taking 0 arguments'
std::thread test2(&This::that, std::ref(t), 1, 2); //runs, but crashes with a Debug error.
}
I have searched, but have only found how to pass arguments to a thread, and to run a function from another class in a thread, but not both!
What is the correct way to do this?
In order to run This in another thread you either have to make a copy or ensure that it is still valid as long as the other thread is running. Try one of these:
Reference
This t;
std::thread test([&]() {
t.that(1,2); // this is the t from the calling function
});
// this is important as t will be destroyed soon
test.join();
Copy
This t;
std::thread test([=]() {
t.that(1,2); // t is a copy of the calling function's t
});
// still important, but does not have to be in this function any more
test.join();
Dynamic allocation
auto t = std::make_shared<This>();
std::thread(test[=]() {
t->that(1,2); // t is shared with the calling function
});
// You still have to join eventually, but does not have to be in this function
test.join();
The object t is destroyed at the end of the main() function, but the thread runs for some time after that. It results in an undefined behavior. It is also generally a good idea to join to all threads before quitting the program. Just put this at the end:
test2.join();
This::that does not take a reference to a This as its first argument.
I think what you want to do is more like
auto t = std::make_shared<This>();
std::thread test2{ [t](int a, int b) { t->that(a, b); }, 1, 2 };

How can let a C++11 thread run several different functions?

I am learning the new multi-threading techniques in C++11. Almost all the tutorials I read on the web is teaching how to launch a new thread(or several threads) executing a function, how to join (or detach) the thread(or threads) later and how to avoid racing conditions using mutex, etc.
But I don't see any of them showing how to make a thread execute several functions at different parts of the program. The question is, with C++11 threads, is it possible to achieve the following? If so, how? (Giving an example will 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 the above main function body into a loop, as following. 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;
}
Reference from cplusplus.com:
default constructor constructs a thread object that does not represent any thread of execution.
Therefore std::thread t simply doesn't define an executable thread. A thread function has to be provided when creating the thread and it cannot be set afterwards.
For your main function version I, you will have to create two threads. Something as 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;
}
Similarly, you can put them in a loop and it is alright which will give you main function version II.
C++11 threading are primitives intended to allow you to write real libraries. They are not easy to use. You should wrap them.
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();
}
};
use looks like:
int main(){
tasks t;
t.start();
t.do([]({std::cout<<"hello ";});
t.do([]({std::cout<<"world\n";});
}
if you want to know when a task is done, check the future do returns.
Written on phone, not compiled, probably full of typos and errors, but a place to start.
Does not support abort early. Easy to write abaondon which empties work.
Supports multiple consumers (workwe threads) I suspect. On compliant system, at dtor will wait for all threads to finish the queued jobs. Not on MSVC2013 tho.