void f(vector<int>& v){
for(const auto& x:v) cout << x;
}
class F{
private:
vector<int> v;
public:
F(vector<int>& vc):v{vc}{}
void operator()(){
for(const auto& x:v) cout << x;
}
};
int main()
{
vector<int> some_vec{3,5,77,32,1};
vector<int> vec{66,8,90,45,777};
thread t1{f,some_vec};
thread t2{F(vec)};
t1.join();
t2.join();
cout << '\n';
}
An error "no type named 'type' in 'class std::result_of< void (*(std::vector))(std::vector&)>' occur
If the argument vector in f is declared as const, void f(const vector<int>& v), the error disappears.
On the other hand, the code with function object F works just fine.
Code from Bjarne Stroustrup -- the C++ programming language 5.3.2 Passing Arguments
std::thread stores copies of the arguments passed to its constructor, and then uses rvalues of those copies as the arguments for a handler. That is, function f cannot be called with an rvalue of std::vector, as it expects a non-const lvalue reference. Even if you change it to a const lvalue reference, then it's a copy of what is actually passed to the t1's constructor.
On the contrary, class F has an implicitly defined copy-constructor, and its function call operator expects no arguments, hence you get no errors. (And F itself is constructed before it's passed to a thread's constructor).
If you want function f to operate on the some_vec instance, you'd have to wrap it with a reference wrapper:
#include <functional>
std::thread t1{f, std::ref(some_vec)};
// ~~~~~~~^
Related
I am in the process of writing a multithreaded TCP server. I am going to have one thread handle incoming socket connections, and spin off threads to handle the communication on those sockets. However, I want the thread handling socket connections to take as parameters a callback function with supporting parameters, and the compiler is complaining. Here is code to illustrate my problem:
template<class Function, class... Args>
void handleIncomingConnectionRequests(Function&& f, Args... args)
{
f(args...);
}
void callback(int x)
{
std::cout << x << "\n";
}
void main()
{
std::thread handleIncomingConnectionsThread(handleIncomingConnectionRequests<decltype(callback)>, callback, 5);
handleIncomingConnectionsThread.join();
}
When I attempt to compile this with clang on Windows, I get a fairly large compilation stack error, but the relevant issue seems to be the following:
error: too few arguments to function call, expected 1, have 0
f(args...);
Why does args appear to have no parameters? I'm clearly passing two arguments to the std::thread constructor. I have clearly done something wrong in the way I am passing the variables in, but I'm not sure how to resolve the issue.
EDIT: It was pointed out that I failed to define the second template argument. I have updated the code to read:
template<class Function, class... Args>
void handleIncomingConnectionRequests(Function&& f, Args... args)
{
f(args...);
}
void callback(int x)
{
std::cout << x << "\n";
}
void main()
{
std::thread handleIncomingConnectionsThread(handleIncomingConnectionRequests<decltype(callback), int>, callback, 5);
handleIncomingConnectionsThread.join();
}
I now get this error:
error: no matching function for call to 'invoke'
This error comes from the xthread file, part of the implementation of the C++ standard library for the thread include file.
Change
std::thread handleIncomingConnectionsThread(handleIncomingConnectionRequests<decltype(callback), int>, callback, 5);
to
std::thread handleIncomingConnectionsThread(handleIncomingConnectionRequests<decltype(callback)*, int>, callback, 5);
or
std::thread handleIncomingConnectionsThread(handleIncomingConnectionRequests<decltype(&callback), int>, callback, 5);
Well I have an issue with passing data into a thread using std::thread. I thought I understood the general semantics of copy constructors, etc. but it seems I don't quite grasp the problem. I have a simple class called Log that has hidden it's copy constructor thusly:
class Log
{
public:
Log(const char filename[], const bool outputToConsole = false);
virtual ~Log(void);
//modify behavior
void appendStream(std::ostream *);
//commit a new message
void commitStatus(const std::string str);
private:
//members
std::ofstream fileStream;
std::list<std::ostream *> listOfStreams;
//disable copy constructor and assignment operator
Log(const Log &);
Log & operator=(const Log &);
}
now I have a main based heavily on http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp
int main()
{
static int portNumber = 10000;
Log logger("ServerLog.txt", true);
logger.commitStatus("Log Test String");
try {
boost::asio::io_service ioService;
server(ioService, portNumber, logger);
}
catch (std::exception &e)
{
std::cerr << "Exception " << e.what() << std::endl;
logger.commitStatus(e.what());
}
return 0;
}
You can see that main calls the function server and passes the IOService, portNumber and logger. The logger is passed by reference, thusly:
using boost::asio::ip::tcp;
void server(boost::asio::io_service &ioService, unsigned int port, Log &logger)
{
logger.commitStatus("Server Start");
tcp::acceptor acc(ioService, tcp::endpoint(tcp::v4(), port));
while(true)
{
tcp::socket sock(ioService);
acc.accept(sock);
std::thread newThread(session, &sock, logger);
newThread.detach();
}
logger.commitStatus("Server closed");
}
I get a compiler error when I try to pass the logger (or the socket) to the thread by reference, but I do not get the error when passing it to the session() by reference
static void session(tcp::socket *sock, Log &logger)
{
std::cout << " session () " << std::endl;
}
Now I thought that I understood correctly that a reference is the same as passing a pointer. That is, it does not call the copy constructor, it simply passes the pointer, which it lets you syntactically treat like it's not a pointer.
error C2248: 'Log::Log' : cannot access private member declared in class 'Log'
1> \log.h(55) : see declaration of 'Log::Log'
1> \log.h(28) : see declaration of 'Log'
...
: see reference to function template instantiation 'std::thread::thread(_Fn,_V0_t &&,_V1_t)' being compiled
1> with
1> [
1> Fn=void (_cdecl *)(boost::asio::ip::tcp::socket *,Log &),
1> _V0_t=boost::asio::ip::tcp::socket *,
1> _V1_t=Log &
1> ]
However if I modify it to pass a pointer, everything is happy
...
std::thread newThread(session, &sock, &logger);
...
static void session(tcp::socket *sock, Log *logger)
{
std::cout << " session () " << std::endl;
}
Why is passing by reference calling my copy constructor. Is there something special happening here because of std::thread? Did I misunderstand the copy constructor and pass by reference?
I get a different but equally baffling error if I try to use std::move() as it is done in the example. Is it possible my VS2012 is not implementing C++11 correctly?
std::thread takes its arguments by value. You can get reference semantics back by using std::reference_wrapper:
std::thread newThread(session, &sock, std::ref(logger));
Obviously you must make sure that logger outlives the thread.
I get a compiler error when I try to pass the logger (or the socket) to the thread by reference
It is not sufficient for the thread's entrypoint function to take a reference type: the thread object itself takes its arguments by value. This is because you usually want a copy of objects in a separate thread.
To get around this, you may pass std::ref(logger), which is a reference wrapper hiding reference semantics under a copyable object.
I'd like to have a wrapper thread function, i.e. a function executed by a thread which does some extra stuff, and then calls the user function.
template<class F, class... Args>
void wrapper(F&& user_function, Args&&... args) {
// do some extra stuff
user_function(args); // maybe I need to forward args
// do some extra stuff
}
Ok, this could be a nice wrapper, so I need a manager that uses this wrapper function and allows the user to spawn his own threads:
class ThreadManager {
public:
template<class F, class... Args>
std::thread newThread(F&& f, Args&&... args) {
return std::thread(thread_wrapper<F,Args...>, std::forward<F>(f), std::forward<Args>(args)...);
}
};
this way the thread manager SHOULD spawn a thread that uses the wrapper function which, in turn, does its extra work and calls the user function.
But the compiler now says: Attempt to use a deleted function.
The error is in the thread header:
template <class _Fp, class ..._Args, size_t ..._Indices>
inline _LIBCPP_INLINE_VISIBILITY
void
__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>)
{
__invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
}
What am I missing/doing wrong?
[edit]
Using test:
void foo(int i) {
std::cout << "foo: " << i << std::endl;
}
int main(int argc, const char *argv[]) {
ThreadManager mgr;
auto t = mgr.newThread(foo, 10);
t.detach();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
return 0;
}
I'm using Xcode 7.1 with LLVM compiler, but fails on FreeBSD clang 3.3 too.
The Xcode error is:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/thread:337:5: error: attempt to use a deleted function
__invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/thread:347:5: note: in instantiation of function template specialization 'std::__1::__thread_execute' requested here
__thread_execute(*__p, _Index());
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/thread:359:42: note: in instantiation of function template specialization 'std::__1::__thread_proxy >' requested here
int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get());
I'm not sure what is causing the "Attempt to use a deleted function" in your example, I get other errors related to std::thread's bind mechanism.
It appears the way you are spelling out the template arguments for thread_wrapper is not playing nice with std::thread's constructor - in particular when it uses a simplified std::bind internally. The mix of perfectly forwarded function types and std::decayed function pointers seems to upset std::result_of.
we can make it work by applying some std::decay in newThread ourselves:
return std::thread( thread_wrapper<typename std::decay<F>::type,
typename std::decay<Args>::type...>,
std::forward<F>(f),
std::forward<Args>(args)... );
...but to be honest I'm not entirely sure why that works.
Alternatively, with some indirection and more forwarding, we can avoid having to spell out the template arguments.
We just need a functor that forwards to thread_wrapper (or a polymorphic lambda in C++14):
struct wrapper_helper {
template<class F, class... Args>
void operator()(F&& f, Args&&... args) const {
thread_wrapper(std::forward<F>(f), std::forward<Args>(args)...);
}
};
And use it in newThread:
return std::thread(wrapper_helper{}, std::forward<F>(f), std::forward<Args>(args)...);
Here's the full example showing arguments passed by value, reference and rvalue reference working as intended: http://coliru.stacked-crooked.com/a/b75d5a264f583237
Note: For move-only types like std::unique_ptr, you will definitely want to forward args... in thread_wrapper.
I have some homework, and I have troubles understanding, (probably) how passing parameters to std::thread constructor works.
Assume following code (I deleted unneeded parts)
template<typename T, typename Task>
class Scheduler
{
private:
typedef std::unordered_map<std::size_t, T> Results;
class Solver
{
public:
Solver(Task&& task) : m_thread(&Solver::thread_function, std::move(task))
{
m_thread.detach();
}
Solver(Solver&& solver) = default; // required for vector::emplace_back
~Solver() = default;
private:
void thread_function(Task&& task)
{
task();
}
std::thread m_thread;
};
public:
Scheduler() = default;
~Scheduler() = default;
void add_task(Task&& task)
{
m_solvers.emplace_back(std::move(task));
}
private:
std::vector<Solver> m_solvers;
};
template<typename T>
struct Ftor
{
explicit Ftor(const T& t) : data(t) { }
T operator()() { std::cout << "Computed" << std::endl; return data; }
T data;
};
int main()
{
Scheduler<int, Ftor<int>> scheduler_ftor;
Scheduler<int, std::function<int(void)>> scheduler_lambda;
Ftor<int> s(5);
scheduler_ftor.add_task(std::move(s));
scheduler_lambda.add_task([](){ std::cout << "Computed" << std::endl; return 1; });
}
Why it doesn't compile?
MVS2015 is complaining about
functional(1195): error C2064: term does not evaluate to a function taking 1 arguments
functional(1195): note: class does not define an 'operator()' or a user defined conversion operator to a pointer-to-function or reference-to-function that takes appropriate number of arguments
note: while compiling class template member function 'Scheduler<int,Ftor<int> >::Solver::Solver(Task &&)'
While G++ 4.9.2
functional: In instantiation of ‘struct std::_Bind_simple<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’:
required from ‘void Scheduler<T, Task>::add_task(Task&&) [with T = int; Task = Ftor<int>]’
functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’
typedef typename result_of<_Callable(_Args...)>::type result_type;
I suppose there are some problems with std::moving to std::thread.
If you use member function as first thread argument, second argument supposed to be this pointer, pointing to the object to which member function could be called to
UPDATE
Good discussion here
Start thread with member function
I don't follow your code, but addressing the question, a extrapolated answer will be( most of the code is psuedocode)
lets assume that there is a function int test(int name).
thread t0;
t0 = thread(test,32);
thread t1(test,43);
Passing a argument to function.
int temp = 0;
int testfunc(int& q)
{
cout<<q;
}
thread t1;
t1 = thread(testfunc,ref(temp));
In short, you just pass the name of the function that must be run in the thread as the first argument, and the functions parameters follow it in same order as they are in the function definition, for passing by reference you can use the ref() wrapper.See the below example.
#include <iostream>
#include <thread>
#include <string>
using namespace std;
void test(int a,int &a,string test)
{
\\do something
}
int main()
{
int test1 = 0;
string tt = "hello";
thread t1;
t1 = thread(23,&test1,tt);
t1.detach();
return 0;
}
if you are wondering about the use of join() and detach(), refer to this thread: When should I use std::thread::detach?, refer to my answer post in that thread.
A class t_analyser contains a function which performs some operations on a t_data object and outputs the results.
I would like to add to t_analyser a filter capability: a small and fast function
bool filter(const t_data & d) {...}
which allows to skip the analysis (and the output) if some conditions are met for that particular data. The filter should be setted up easily from the main, so I was thinking to store a shared function pointer in t_analyser and use a lambda to initialize it.
Is this a good approach? My concerns are related to the fact that many analysers can call the same filter function simultaneously in different threads, could this be a problem? Can I simply copy the pointer in the t_analyser's copy constructor? Any hint would be much appreciated.
This could be a problem if your filter function had side effects. Its signature is simple and says that it just makes some decision reading data from t_data, so make sure that t_data is not modified in parallel thread and you'll be fine.
Consider the following program:
#include <iostream>
struct X
{
void foo1(){ std::cout << "foo1" << std::endl; }
void foo2(){ std::cout << "foo2" << std::endl; }
};
typedef void (X::*MemberFunctionPointer)();
struct ByRef
{
ByRef( MemberFunctionPointer& f )
: f_( f )
{
}
void operator()()
{
X x;
(x.*f_)();
}
MemberFunctionPointer& f_;
};
struct ByValue
{
ByValue( MemberFunctionPointer f )
: f_( f )
{
}
void operator()()
{
X x;
(x.*f_)();
}
MemberFunctionPointer f_;
};
int main()
{
MemberFunctionPointer p = &X::foo1;
ByRef byRef( p );
ByValue byValue( p );
byRef();
byValue();
p = &X::foo2;
byRef();
byValue();
return 0;
}
Output:
foo1
foo1
foo2
foo1
Press <RETURN> to close this window...
From this you will notice that in the one case the member function pointer is passed by value (and not shared), and in the other it is passed by reference (and shared). When using the syntax:
foo( void( X::*f)() )...
the pointer to member function is passed by value, and is copied (and cannot be modified) again.
You can declare the function pointer as static + thread specific:
static _declspec(thread) FUNC_TYPE filterFunc;
Each thread that modifies filterFunc works on a different copy of the pointer.