I have a function foo(myclass* ob) and I am trying to create a consumer thread using consumer_thread(boost::bind(&foo)(&ob))
The code does not compile which I believe is due to my inappropriate way of passing the function argument to the function pointer.
class myclass{
// stuff
}
void foo(myclass* ob){
// stuff
}
int main(){
myclass* ob = new myclass();
boost::thread consumer_thread()boost::bind(&foo)(&ob));
// stuff
}
What am I doing wrong? Can anyone here elaborate on boost::bind and how to pass function pointers with function arguments?
Thanks in advance!
Your code sample has some errors. This is a fixed version, where the return value of the call to bind is used as the sole parameter in the boost::thread constructor:
boost::thread consumer_thread(boost::bind(foo, ob));
But you can skip the call to boost::bind entirely, passing the function and its parameters to the constructor:
boost::thread consumer_thread(foo, ob);
That should be bind(foo, ob).
However, I'm fairly sure that boost::thread has the same interface as std::thread, in which case you don't need bind at all:
boost::thread consumer_thread(foo, ob);
Related
I can do this to start my thread:
int main_test() {
// do something...
return 0;
}
std::thread* myThread;
void myFunction() {
myThread = new std::thread(main_test);
}
How do I pass main_test as an argument to myFunction, so the same function can be used to start the thread using different target functions? What would the signature of myFunction be then?
I guess what I don't understand is how the templated version of the std::thread constructor is invoked with a specified type.
std::thread myThread;
The type of myThread is std::thread.
myThread = new std::thread(main_test);
new std::thread(main_test) returns std::thread*. You cannot assign std::thread* into a std::thread. The program is ill-formed.
Solution: There appears to be no reason to use dynamic allocation. Simply assign a temporary object like this:
myThread = std::thread(main_test);
How do I pass main_test as an argument to myFunction, so the same function can be used to start the thread using different target functions? What would the identity of myFunction be then?
You can make your myFunction a template with exactly the same arguments as std::thread has, and forward everything. Or, if you want to keep it simple, you can use a function pointer.
How do I pass main_test as an argument to myFunction, so the same function can be used to start the thread using different target functions?
You can pass the poiter to your function as an argument
void myFunction(int (*func)()) {
myThread = new std::thread(func);
}
int callSelector(int someCriteria)
{
if (someCriteria == 0) {
myFunction(main_test1);
}
else {
myFunction(main_test2);
}
}
I'm having a bit of trouble using std::thread together with lambdas. I have a method TheMethod where I should use std::thread to parallelize some function calls to methods in the same class.
I define a lambda function, and try to pass it as follows to the std::thread instance I create:
auto functor =
[this](const Cursor& c, size_t& result) ->void {result = classMethod(c);};
size_t a;
Cursor cursor = someCursor();
std::thread t1(functor, cursor, a);
t1.join();
Unfortunately, the compiler gives me:
/usr/include/c++/4.8/functional:1697:61: error: no type named ‘type’ in ‘class std::result_of<TheMethod...
I tried a lot of combinations in the lambda definition, and in the way of calling the std::thread constructor, but I get the same error always. The thread library is included, I link pthread too.
Thanks for hints!
You can use std::ref to pass the parameters by reference:
std::thread t1(functor, std::ref(cursor), std::ref(a))
You could also capture the parameters by reference in the lambda itself:
size_t a;
Cursor cursor = someCursor();
std::thread t1([&] {a = classMethod(cursor);});
t1.join();
This is because the objects cursor and a are passed by value to the constructor of thread. The functor takes a reference to the local copies of the newly created thread and not on the objects you expected them to be.
Hence, as answered by "alexk7", you should use std::ref or if you want to capture them pass by reference.
I am trying to run a member function in its own thread and have followed this post, however in that example, the thread starts and finishes in the same function. How do you maintain a reference to the thread to join in a separate member function (say the destructor)? I have tried this:
class foo
{
foo();
~foo();
volatile sig_atomic_t m_run_thread = true;
std::thread &m_read_thread;
void read_thread();
}
foo::foo():m_read_thread(std::thread(&foo::read_thread, this))
{
}
foo::~foo()
{
m_run_thread = false;
m_read_thread.join();
}
void foo::read_thread()
{
while(m_run_thread)
{
//do something cool
}
}
int main()
{
foo bar;
//do other stuff
}
The compiler gives me an error though: error: invalid initialization of non-const reference of type ‘std::thread&’ from an rvalue of type ‘std::thread’. This is caused because I'm trying to bind a temporary to a reference. What's this best way to fix this?
foo::foo():m_read_thread(std::thread(&foo::read_thread, this)) is not going to work as std::thread(&foo::read_thread, this) is a temporary value and a temporary cannot be bound to a non const lvalue reference.
That said there is no reason to make the thread member a reference. You can simple have a std::thread member like std::thread m_read_thread; and then in the constructor you would initialize it like
foo::foo() : m_read_thread(std::thread(&foo::read_thread, this))
Need to have this Functor live as long as my thread does, so I've created a shared_ptr to it and trying to pass it to std::thread. I've copied the code and list of errors here.
struct Functor
{
std::string greeting;
explicit Functor(std::string _greeting="Hello!"): greeting { _greeting } {}
void operator()()
{
std::cout << greeting << "\n";
}
};
auto main() ->int
{
std::shared_ptr<Functor> fp = std::make_shared<Functor> ();
std::thread t(&fp);
t.join();
return 0;
}
List of errors:
Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)' std_threads C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\thr\xthread 240
Error C2672 'std::invoke': no matching overloaded function found std_threads C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\thr\xthread 240
I'm new to c++11 and concurrency. Please help me understand the following
1>does a std::thread always invoke the operator() inside an object when passed by value ? If so, why it has been defined so.
2>how to ensure that a resource given to a thread stays around as long as the thread does?
3>is the Functor written here, a function object ?
4>What have I done here in this code ?!
1>does a std::thread always invoke the operator() inside an object
when passed by value ? If so, why it has been defined so.
std::thread invokes std::invoke. From cppreference, if the first argument is neither a pointer to member function nor a pointer to data member; it is treated as a function object.
So, fp() will be called.
INVOKE(f, t1, t2, ..., tN) is equivalent to f(t1, t2, ..., tN) (that
is, f is a FunctionObject)
So you can basically do std::thread t{*fp}
2>how to ensure that a resource given to a thread stays around as long
as the thread does?
You can have shared_ptr to provide ownership of a shared object. Or you can just manually do it by ensuring the resource passed is in scope. The mileage varies.
3>is the Functor written here, a function object ?
Yes. A FunctionObject type is the type of an object that can be used on the left of the function call operator. However fp is not. But *fp is.
4>What have I done here in this code ?!
You can make it work by explicitly passing Functor::operator() with argument fp.get(). Ofcourse a simple way is to just pass *fp
Demo
std::shared_ptr<Functor> is not callable - it doesn't implement operator(), even while Functor does.
What's the purpose of shared_ptr here? Why not simply
int main() {
Functor f;
std::thread t(std::ref(f));
t.join();
return 0;
}
If for some reason you insist on having Functor instance managed by a shared_ptr, here's one way:
int main() {
std::shared_ptr<Functor> fp = std::make_shared<Functor> ();
std::thread t([fp]() { (*fp)(); });
t.join();
return 0;
}
You can still make std::thread take ownership of your smart pointer with this syntax:
std::shared_ptr<Functor> f = std::make_shared<Functor>();
std::thread thread (&Functor::operator(), f);
thread.detach();
If the first argument is a member function pointer, then the second argument is expected to be a reference or pointer to an instance of the class and std::shared_ptr<Functor> is accepted. When the thread finishes, the smart pointer will be deleted.
Downside: removes the benefit of having a functor because you have to specify the member function.
I'm having a bit of trouble using std::thread together with lambdas. I have a method TheMethod where I should use std::thread to parallelize some function calls to methods in the same class.
I define a lambda function, and try to pass it as follows to the std::thread instance I create:
auto functor =
[this](const Cursor& c, size_t& result) ->void {result = classMethod(c);};
size_t a;
Cursor cursor = someCursor();
std::thread t1(functor, cursor, a);
t1.join();
Unfortunately, the compiler gives me:
/usr/include/c++/4.8/functional:1697:61: error: no type named ‘type’ in ‘class std::result_of<TheMethod...
I tried a lot of combinations in the lambda definition, and in the way of calling the std::thread constructor, but I get the same error always. The thread library is included, I link pthread too.
Thanks for hints!
You can use std::ref to pass the parameters by reference:
std::thread t1(functor, std::ref(cursor), std::ref(a))
You could also capture the parameters by reference in the lambda itself:
size_t a;
Cursor cursor = someCursor();
std::thread t1([&] {a = classMethod(cursor);});
t1.join();
This is because the objects cursor and a are passed by value to the constructor of thread. The functor takes a reference to the local copies of the newly created thread and not on the objects you expected them to be.
Hence, as answered by "alexk7", you should use std::ref or if you want to capture them pass by reference.