I am using g++ 4.7 with the c++11 flag. In this demo:
#include <iostream>
#include <thread>
class do_work
{
public:
void operator()()
{
std::cout << "Doing work..." << std::endl;
}
};
void foo()
{
}
int main()
{
// Does not work
std::thread t(do_work);
t.join(); // error: request for member ‘join’ in ‘t’, which is of non-class type ‘std::thread(do_work)’
// Works
std::thread t2(foo);
t2.join();
return 0;
}
I can successfully call join() on a thread that was created with a function as its constructor argument, but I cannot call join() (see the error inline) on a thread that was created with a functor as its constructor argument. Can anyone explain this?
You've declared t as a function taking do_work and returning std::thread.
You probably want to write
do_work worker;
std::thread t{worker};
or
std::thread t{do_work{}};
or
std::thread t((do_work()));
Note that
std::thread t(do_work());
won't work; it's vexingly parsed as declaring a function t taking a function that takes no arguments and returns do_work, and returning std::thread. Wrapping the do_work temporary with parentheses or using uniform initializer syntax (at any point) will fix it.
This is a good reason to get into the habit of using uniform initializer syntax wherever possible; if you'd written
std::thread t{do_work}; // incorrect
then compilation would have failed on that line instead of the join.
Related
I have a member function which I cannot unit test easily (it listens to sockets etc):
void MyClass::func()
{
listen();
send();
}
So I want to template it and then I can pass a mock object in my test:
template<class OBJECT>
void func(OBJECT& obj)
{
obj.listen();
obj.send();
}
and then I'd do:
func(*this);
The above compiles when I do a normal function call. However, when I spawn a thread and call it:
std::thread t1(&MyClass::func, this, *this);
I get compiler errors (see below) referring to decltype. Is there a way I can still achieve this?
/opt/gcc-8.2.0/lib/gcc/x86_64-unknown-linux/8.2.0/../../../../include/c++/8.2.0/thread:127:8: note: in instantiation of template class 'std::thread::_Invoker<std::tuple<void (MyClass::*)(MyClass &),
MyClass *, MyClass> >' requested here
__make_invoker(std::forward<_Callable>(__f),
However, the following works:
void MyClass::x()
{
func(*this);
}
std::thread t1(&MyClass::x, this);
There are two issue in your code:
First, you cannot pass function templates to the std::thread constructor. You must explicitly specify what specialisation of the function template to use, which in this case, would be &MyClass::func<MyClass>.
Second you are trying to pass a reference as an argument to the constructor of std::thread. When the std::thread constructor is called, the first argument is the function to run concurrently, and the others are the argument to the function. The other arguments are moved and then passed as argument to the function. This is fine if the argument is a pointer or a variable, but causes an issue if the function expects a non-const lvalue as an argument.
You can solve both issues by constructing std::thread with lambdas:
std::thread t1([=]{
this->func(*this);
});
Conversely, you could use std::ref, a reference wrapper, in the std::thread constructor, and explicitly specify the function template specialisation:
#include<functional>
std::thread t1(&MyClass::func<MyClass>, this, std::ref(*this));
Personally, I much prefer constructing std::threads with lambdas, as it is cleaner and less error prone.
I'm kind of new to std::async and I have problems understanding how it works. I saw example of how to pass member funcion to std::async somewhere on the web but it seems not to compile. Whats the problem here? How can it be done without lambda?
class Test {
std::future<void> f;
void test() {}
void runTest() {
// ERROR no instance overloaded matches argument list
f = std::async(std::launch::async, &Test::test, this);
// OK...
f = std::async(std::launch::async, [this] {test();});
}
void testRes() {
f.get();
}
};
You should be able to use std::bind to create a callable function object:
f = std::async(std::launch::async, std::bind(&Test::test, this));
In your example &Test::test is not a function that takes one parameter of type Test, as it would be expected by std::async. Instead it is member function, which must be called differently.
What is a once_flagsupposed to be initialized to? I've tried false and 0, and both have given errors similar to below (below is 0):
no viable conversion from 'int' to 'std::once_flag'
Here's how I am trying to use it. (I consider it bad style to not initialize statics even though the language initializes them, so I'd really prefer to have something there).
MyClass& GetMyClass()
{
static std::once_flag flag;
static MyClass cls;
std::call_once(flag, []() {
// Initialize class
});
return cls;
}
Update
If we look at the draft C++ standard section 30.4.4.1 Struct once_flag we can see the constructor is defined as:
constexpr once_flag() noexcept;
since it is a constexpr your static instance will be statically initialized and we can see an example in section 30.4.4.2 Function call_once that uses a static instance:
void g() {
static std::once_flag flag2;
std::call_once(flag2, initializer());
}
Original
If we look at the documentation to std::once_flag it says:
once_flag();
Cnstructs an once_flag object. The internal state is set to indicate that no function
has been called yet.
and if we look further at the document documentation for call_once we see the following example which demonstrates how to use std::once_flag:
#include <iostream>
#include <thread>
#include <mutex>
std::once_flag flag;
void do_once()
{
std::call_once(flag, [](){ std::cout << "Called once" << std::endl; });
}
int main()
{
std::thread t1(do_once);
std::thread t2(do_once);
std::thread t3(do_once);
std::thread t4(do_once);
t1.join();
t2.join();
t3.join();
t4.join();
}
with the following expected output:
Called once
Since your question has been answered elsewhere, as an alternative to the code you posted, you can also do this instead:
// private function in anonymous namespace or something
MyClass& initMyClass() {
static MyClass c;
/* initialize c */
return c;
}
and then have clients call
MyClass& GetMyClass() {
static MyClass& c = initMyClass();
return c;
}
because static initializations are thread safe now in C++11. And then you don't have to mess with call_once or anything.
what are you trying to do? you cannot initialize std::once_flag with any value because it only has one constructor that does not take any arguments.
http://en.cppreference.com/w/cpp/thread/once_flag
once_flag(); Constructs an once_flag object. The internal state is set
to indicate that no function has been called yet.
BTW, what is the reason that you consider not initialize statics variable is a bad style?
ONCE_FLAG_INIT
EDIT: C only, not C++. Defined in <threads.h>.
i am using the c++11 thread library with classes, and it works fine.
I just need an explanation for this code so i understand it correctly.
My class.h
class foo {
private:
std::thread t1;
void worker();
public:
void work();
};
the class.cpp
#include "class.h"
void foo::worker() {
std::cout << "worker..." << std::endl;
}
void foo::work() {
t1 = std::thread(&foo::worker, this);
t1.join();
}
and now the main.cpp
#include "class.h"
int main(int argc, char **argv) {
foo bar;
bar.work();
}
What I don't really understand is the invocation of the class-function for the thread.
I use std::thread(&foo::work, this) and interpret this call as follows:
The first parameter is the pointer to the function, but i dont know why i cant just call it
without the &foo:: part.
The second parameter is the class itself that the thread knows the parent process?
I couldn't find a explaination for this. Only the code and i would like to understand it.
Thanks!
&foo::work is required because work is a member function that belongs to class foo. A (non-static) member function can only be accessed if also the object it belongs to is known.
The this parameter is a pointer to the object of which the method should be called.
The address bit is just the syntax for expressing the address of a member function. I believe this could also be expressed as this->worker. I don't know why worker by itself is not allowed---it seems unambiguous, but that's C++.
You have to pass both the member function pointer and this so that the thread can invoke the member function on the correct object. Internally the thread holds a member function pointer, say pmf (pointing to foo::worker), and the object pointer, say po (pointing to the this that was passed). It needs to be able to invoke (po->*pmf)(), which result in worker being invoked on the correct object.
Could you tell mw what is the problem with the below boost::thread program
#include<iostream>
#include<boost/thread/thread.hpp>
boost::mutex mutex;
class A
{
public:
A() : a(0) {}
void operator()()
{
boost::mutex::scoped_lock lock(mutex);
}
private:
int a;
};
int main()
{
boost::thread thr1(A());
boost::thread thr2(A());
thr1.join();
thr2.join();
}
I get the error message:
error: request for member 'join' in 'thr1', which is of non-class type 'boost::thread()(A ()())'
BoostThread2.cpp:30: error: request for member 'join' in 'thr2', which is of non-class type 'boost::thread ()(A ()())'
You have stumbled on something wonderfully known as the most vexing parse. The quickest way to fix that is to add an extra set of parentheses:
boost::thread thr1((A()));
You can also introduce a temporary:
A tmp1;
boost::thread thr1(tmp1);
In the most vexing parse, what you think is generating a temporary is parsed as if it's a function taking no parameters. It then treats thr1 as a prototype to a function that takes a single parameter (which is the function mentioned previously) and returning a boost::thread.
This is a classic C++ trap. thr1 is not what you think it is (a thread object). It's the declaration of a function that takes an instance of A as a parameter. Wrap it in parentheses to force the intended interpretation:
boost::thread thr1((A()));
boost::thread thr2((A()));
The detailed explanation
Syntactically, the original syntax is equivalent to:
boost::thread thr1(A);
Why is the compiler allowed to ignore the empty parentheses? Frankly, I'm not sure — I'm not a C++ language expert — but I think it has to with the following train of thought: A *a = A (*a), therefore A * = A (*); likewise, A a = A (a), therefore A = A ().
Look to the future!
The upcoming C++ standard will fix this as a byproduct of its new initialisation syntax:
boost::thread thr1{A()};
boost::thread thr2{A()};