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()};
Related
I'm trying to write a class include a public thread object, and finally I want to access this thread ouside the class, but there are some errors, why?
The class defined as:
class scoped_thread {
public:
std::thread t;
explicit scoped_thread(std::thread t_) : t(std::move(t_)) {
if (!t.joinable())
throw std::logic_error("No thread");
}
~scoped_thread() {
// t.join();
}
scoped_thread(scoped_thread const &) = delete;
scoped_thread & operator = (scoped_thread const &) = delete;
};
and I'm try to access thread member:
scoped_thread th(std::thread(f));
th.t.join();
At last, the error is:
error: request for member 't' in 'th', which is of non-class type 'scoped_thread(std::thread)'
scoped_thread th(std::thread(f)); is a declaration of a function named th, returning scoped_thread and taking std::thread as a parameter. It's not a declaration of an object of type scoped_thread. Naturally, the function doesn't have members, named t or otherwise.
See also: most vexing parse.
You've run into the most vexing parse. C++ thinks you've declared a function named th instead of an object. In recent versions of C++, to correct the issue you can use curly braces instead of parentheses.
scoped_thread th{std::thread{f}}; // compiles as expected
In Qt Creator, using C++ I have to call the same function from another class for many times. However this slows down the overall performance speed. So in order to do real-time operation, I thought of using multithreading. After some search I found Qt Concurrent might help so tried the following steps.
My target function is in this class:
Class myClass
{
public foo(std::vector<float> inputVec, std::string inputStr);
}
And in my main class, I do this:
std::vector<float> mvec;
// here put some values into mvec;
std::string mstring = "test";
myClass mcl;
QFuture<float> f1 = QtConcurrent::run(mcl.foo(mvec, mstring));
f1.waitForFinished();
However, this gives out error saying:
no matching function for call to 'run(float)'
'functor' cannot be used as a function
'float' is not a class, struct, or union type
...
I also tried to use std::thread like this:
std::thread t1 = std::thread(mcl.foo, mvec, mstring);
if(t1.joinable()) t1.join();
But this throws the following error:
invalid use of non-static member function
I've tried many example codes online but still confused. How can I make this code to run smoothly and thread safe? Thank you.
The following statement, executes the foo method and passes the result of it to the run function.
QtConcurrent::run(mcl.foo(mvec, mstring));
The correct form is:
QtConcurrent::run(&mcl, &myClass::foo, mvec, mstring);
Also note that calling f1.waitForFinished(); after that, actually blocks your thread until the foo method completes. So you won't gain any advantage of multithreading.
You have to pass the (member-)function itself (plus the object the member shall relate to), not the result of just calling it. Have a look at the documentation:
QtConcurrent::run() also accepts pointers to member functions. The
first argument must be either a const reference or a pointer to an
instance of the class. Passing by const reference is useful when
calling const member functions; passing by pointer is useful for
calling non-const member functions that modify the instance.
For example, calling QByteArray::split() (a const member function) in
a separate thread is done like this:
// call 'QList<QByteArray> QByteArray::split(char sep) const' in a
separate thread QByteArray bytearray = "hello world";
QFuture<QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split, ',');
...
QList<QByteArray> result = future.result();
Thus, your code should rather look like
myClass mcl;
QFuture<float> f1 = QtConcurrent::run(&mcl, &myClass::foo, mvec, mstring);
f1.waitForFinished();
Say I have an object called myObject of class myClass. It has a function
void myFunction()
What is the syntax to call this function with a thread?
I tried
std::thread myThread(myObject.myFunction)
but I'm given a syntax error and can't seems to find the correct syntax.
The error message is:
function "std::thread::thread(const std::thread &)" cannot be referenced -- it is a deleted function
Thanks for any help.
You can write:
std::thread myThread(std::bind(&myClass::myFunction, myObject));
Being, myClass the class name of myObject. This is the syntax for a pointer-to-member-function.
Also, you can add any other argument your myFunction requires just after myObject.
according to GCC , here is the error : http://coliru.stacked-crooked.com/a/4fcba365c9b25d1e
which makes sense, because member function is bound to this pointer , member variabes and many more. I'd go with lambda expression :
std::thread t ([&]{
myObject.myFunction();
})
working example : http://coliru.stacked-crooked.com/a/0be834a7249bfac9
btw, this practice of wrapping everything with anonymous function is very common in JavaScript, and should be used also here
Possible duplicate.
std::thread myThread(&myClass.myFunction, myObject)
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.
Here is the example of the "scoped lock" idiom with common mistake: no local variable is created, so lock is not in effect. This code compiles flawlessly both with VC++ 2010 and Comeau C++ online:
class Mutex
{
public:
void lock() {}
};
class ScopedLock
{
public:
ScopedLock() : m_pm(0) {}
ScopedLock(Mutex& m) : m_pm(&m) { m_pm->lock(); }
private:
Mutex* m_pm;
private:
ScopedLock& operator =(const ScopedLock&);
ScopedLock(const ScopedLock&);
};
class X
{
public:
void foo() const
{
ScopedLock(m_mutex);
}
private:
Mutex m_mutex;
};
int main()
{
X x1;
x1.foo();
}
If default constructor for ScopedLock is commented out, then both compilers give an error:
error C2512: 'ScopedLock' : no appropriate default constructor available
(When ScopedLock used correctly, i.e. local variable is created: ScopedLock guard(m_mutex);, then compilation fails as expected. Declaring m_mutex as mutable fixes the problem.)
I have two questions:
Why X::foo compiles? It seems that compiler was able to cast const Mutex& to Mutex& somehow.
What role plays ScopedLock default constructor, so the compilation succeeds?
Thanks.
Update: I found the answer. It appears that ScopedLock(m_mutex); statement creates a local variable m_mutex of type ScopedLock. Not a temporary. That's why ScopedLock::ScopedLock default constructor is required.
You answered the question yourself.
It appears that ScopedLock(m_mutex); statement creates a local variable m_mutex of type ScopedLock
The explanation is to be found in the Standard's Section 6.8 Ambiguity Resolution:
There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion [5.2.3] as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.
The Standard then lists T(a); as an example of a statement that is really a declaration. It is equivalent to T a;
This is one variation of the infamous C++ "most vexing parse".
I'm pretty sure your problem is line 26: ScopedLock(m_mutex);
Instead, that should be something like ScopedLock a_variable_name(m_mutex);
When I make that change, I get the expected errors:
constCorrectness.cpp: In member function ‘void X::foo() const’:
constCorrectness.cpp:26: error: no matching function for call to ‘ScopedLock::ScopedLock(const Mutex&)’
constCorrectness.cpp:18: note: candidates are: ScopedLock::ScopedLock(const ScopedLock&)
constCorrectness.cpp:11: note: ScopedLock::ScopedLock(Mutex&)
constCorrectness.cpp:10: note: ScopedLock::ScopedLock()
Perhaps somebody can interpret ScopedLock(m_mutex) for us? Does it declare a function or something? Instead of calling a constructor as expected by the questioner? Update: Striking this out. I think it's just a variable declaration (i.e. the brackets are ignored.)
The problem is that the X::foo() method is declared as const - that means that it will not mutate (change) the object.
The ScopedLock() constructor doesn't have a overload that accepts a immutable (const) reference to a Mutex object.
Fixing this requires you declare m_mutex as mutable, or provide an appropriate overloaded ScopedLock() constructor. I'm thinking the former is preferable.