So C++11 threads are wrappers around pthreads on most systems, I am confused how the syntax for going from a variadic function to a more strict function with a specified return type might work (i.e. the callback function with pthreads) can someone give an example that could illustrate the same?
Suppose you have a C style interface that looks like:
Foo run( Foo(*)(void*), void* );
And you want to write:
template<class F, class...Args>
std::result_of<F(Args...)>
smart_run( F&& f, Args&&... args );
This is analogous to what you need to do to implement std::thread on top of pthreads. I simplified stuff a bit, because it is noise (no std ref support, no decaying, etc).
For the first step, take F and Args... and bind them up. Something like std::bind(f, args...) that returns a zero-arg function that returns the result.
With that, we just need to solve:
template<class F>
std::result_of<F()>
smart_run( F&& f );
which takes an arbitrary callable, then uses run above to run it.
The trick is to create a copy of f on the free store and a function that calls it like this:
template<class F>
std::result_of<F()>
smart_run( F&& f ){
struct data{
F f;
std::result_of_t<F()> r;
};
data*p = new data{std::forward<F>(f)};
Foo ignored=run(
[](void* p){
data* self=static_cast<data*>(p);
auto& f=self->f;
self->r = f();
return Foo{}; // whatever
},
p
);
auto r=data->r;
delete data;
return r;
}
Now, the r is assigned instead of constructed. But the core of the idea -- that you pass the fancy callable in the void*, andmthe function unwraps it and interacts with it, and done is there.
In a real thread on pthread, you'd pass a pointer-to-std::thread-state to the pthread invoker. It would set whatever up, invoke the stored procedure, and when done would take the return value and store it in the internal std::thread state (if needed). Then you could get that data by interacting with the internal std::thread state.
Or something else roughly equivalent.
Related
I am trying to get a thread pool to run a method were the arguments are passed by reference. The
method I want to run is:
void Foo(const std::vector<std::string> &arg1, std::vector<int> &arg2, int size) {//modify elements of arg2}
I am submitting this function to a thread pool:
Pool.submit(Foo, arg1,arg2,size);
...
template<typename F, typename... Args>
void submit(F&& f, Args&&... args) {
//Create a callable std::function with parameters that will be executed by a free std::thread
std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
//Place the callable std::function into a shared_ptr
auto pTask = std::make_shared<std::packaged_task<decltype(f(args...))()>> (func);
//Wrap packaged task into void std::function using a lambda std::function
std::function<void()> pWrappedTask = [pTask]() {(*pTask)();};
//Increment this for job status tracking
JobsRequested++;
//Enqueue generic wrapper std::function
JobQ.enqueue(pWrappedTask);
//Wake up one std::thread if its waiting
PoolCondVar.notify_one();
}
I found that the the arguments are not being passed by reference, so when the thread calls Foo, the original variable does not get modified. If I call the function without using the thread pool, the Foo works correctly. I think it has something to do with how I am setting up the function std::function<decltype(f(args...))()> func = std::bind(std::forward<F>(f), std::forward<Args>(args)...); because when I debug the function within each thread, the address of my arguments change between threads.
Thank you for any suggestions!
According to std::bind documentation:
The return type of std::bind holds a member object of type std::decay<F>::type constructed from std::forward<F>(f), and one object per each of args..., of type std::decay<Arg_i>::type, similarly constructed from std::forward<Arg_i>(arg_i).
Thanks to decay, the arguments are "stored-by-value", which means the arguments are either copy-constructed or move-constructed. This explains their different address.
As usually in such situations, the solution is in using std::reference_wrapper:
Pool.submit(Foo, std::ref(arg1), std::ref(arg2), size);
Live demo: https://godbolt.org/z/4M3vK1cr9
I have been learning about perfect forwarding and the use of && in function templates (see this previous question of mine) and would like to know if my use of Args&& in StartDetachedThread() below is justified:
#include <thread>
class CObject {};
void MyThreadFunc(CObject&)
{
}
// ** Will not compile with this function declaration! **
void MyThreadFunc(CObject&&)
{
}
template<typename FunctionType, typename ...Args>
void StartDetachedThread(FunctionType func, Args&&... args)
{
thread([&]()
{
func(forward<Args>(args)...);
}).detach();
}
int main()
{
CObject object;
StartDetachedThread(MyThreadFunc, object);
CObject object2;
StartDetachedThread(MyThreadFunc, std::move(object2));
return 0;
}
This code simply creates a detached thread, running the supplied function passing to it the supplied arguments.
Hhowever, VS 2017 complains:
'StartDetachedThread': no matching overloaded function found
'void StartDetachedThread(FunctionType,Args &&...)': could not deduce template argument for 'FunctionType'
1) I know that arguments passed to the thread constructor are copied first, then passed by reference to the new thread, so is my attempt to have MyThreadFunc(CObject&&) called when I pass an rvalue reference never going to work?
2) Is there any value in having StartDetachedThread(FunctionType&& func, Args&&... args) - or is the && unnecessary for FunctionType?
3) Is there any value whatsoever in using Args&& when starting a thread like this, or should I always use Args?
The problem in your code has nothing to do with std::thread, it is because MyThreadFunc is ambiguous in this context:
// Which MyThreadFunc should be used?
StartDetachedThread(MyThreadFunc, object);
Regarding your question:
1) I know that arguments passed to the thread constructor are copied first, then passed by reference to the new thread, [...]
In your example, the only copy is the copy of the lambda. The arguments are not copied here, if you want the argument to be copied you should use something like this:
std::thread(std::move(func), std::forward<Args>(args)...).detach();
...where you forward the arguments to std::thread constructor.
This is safer. — Think about what happens if the function StartDetachedThread ends while the thread is still running?
If you use this, you need to explicitly tell the compiler you want to call the reference version for object1 by using std::ref:
CObject object;
StartDetachedThread<void (CObject&)>(MyThreadFunc, std::ref(object)); // std::ref
CObject object2;
StartDetachedThread<void (CObject&&)>(MyThreadFunc, std::move(object2));
2) Is there any value in having StartDetachedThread(FunctionType&& func, Args&&... args) - or is the && unnecessary for FunctionType?
3) Is there any value whatsoever in using Args&& when starting a thread like this, or should I always use Args?
Using forwarding references allows you to call StartDetachedThread without having to move everything. If you use the above way for constructing a std::thread, then copies will be made for func and args anyway.
The issue is that which overload of MyThreadFunc is desired is not deducible by the compiler. There are at least two ways to fix it:
Rename one of the function so that it is clearer which one you want.
Use explicit template parameters:
StartDetachedThread<void (CObject&)>(MyThreadFunc, object);
StartDetachedThread<void (CObject&&)>(MyThreadFunc, std::move(object2));
I am using a function (not mine, from a library I don't control) with a signature similar to this:
template<typename T, typename F>
void do_async(T const&, F); // the second parameter is a callable
and it usually used like this
do_async(obj, [this](){ ... });
I wrote a function similar to this that always uses the same callback lambda:
template<typename T>
void do_async_wrapper(T obj) {
do_async(obj, [this](){ ... });
}
My problems stem from the fact that since the obj is passed as a reference, it has to be kept alive until the callback is called. My function is supposed to take care of that so the caller doesn't have to worry about object lifetime. That is why it accepts by value.
I would like to do something like this in order to keep it alive:
template<typename T>
void do_async_wrapper(T obj) {
do_async(obj, [this, obj{std::move(obj)}](){ ... });
}
Obviously this wont (always) work as-is since the reference points to the function-local one which doesn't exist anymore, while the one kept alive is a (move-)copy of it.
Any suggestions?
As the functor is taken by value, you cannot store the object directly in the functor and pass a reference to it.
You may work-around that by using smart pointer as shared_ptr:
template<typename T>
void do_async_wrapper(T obj) {
auto ptr = std::make_shared<T>(std::move(obj));
do_async(*ptr, [this, ptr](){ /*...*/ });
}
#include <iostream>
#include <functional>
template <typename... Args>
std::function<void(Args...)> pushToEventLoop(std::function<void(Args...)> && p_function)
{
auto func = [p_function](Args... args) ->void
{
// This is what i would do here, but requires too much source code
//ThreadPool::enque(std::bind(p_function, args...));
// This is what i'll do for the sake of the example.
p_function(args...);
};
return func;
}
int main()
{
auto function(pushToEventLoop(std::function<void(char const *)>(std::bind(std::printf, std::placeholders::_1))));
auto function2 = std::bind(function, "Hello World!\n");
function2();
return 0;
}
Is it possible and how, to return the "func" variable by rvalue ref?
I have a feeling that this is somehow totally insane, but I'd like to know why, so I can restore my sanity.
I have no idea if i have done something horribly wrong. Please provide feedback.
I built this thing so that I can make callbacks that are actually just posted to the treadpool for processing, without the caller or the target knowing anything about this. The middleman that binds them together makes the choice of how to connect them.
https://ideone.com/4Wfhb1
EDIT
Ok, so I thought that there is copying going on when I return the func variable. But apparently it's dealt with by RVO, so no copying takes place. I have not verified this, but now that I think about it, that would make sense.
If your question is how to return a lamba in the most eficient way, then just return it by value and use automatic return typ deduction:
//this will actually return a lmabda and not a std::function
template <typename... Args>
auto pushToEventLoop(std::function<void(Args...)> && p_function)
{
return [f = std::move(p_function)](Args... args)
{
f(args...);
};
}
This will leverage RVO and avoid any dynamic memory allocations that std::function might have to perform.
Also having an r-value reference parameter usually doesn't gain you anything, if you don't move from it (unless you require that specific interface for another reason). In order to do so here you can leverage c++14's generalized lambda capture (the compiler can't perform that optimization by itself, as p_function itself is an l-value).
Now, if your question on the other hand was, if/how you can return a (r- or l-value) reference to a non-static local variable from a function, then the answer is simply:
NEVER DO THAT!
I think what you're trying to do is to move p_function into your lambda while avoiding copies? Presumably this is for performance reasons?
In which case you probably want to write it like this:
template <typename... Args>
// return by value - because RVO will elide copies for us
std::function<void(Args...)>
// passing by r-value reference... ok no problem there
pushToEventLoop(std::function<void(Args...)> && p_function)
{
// but I want to MOVE my p_function into func
// this will require at least c++1y (c++14)
auto func = [p_function = std::move(p_function)](Args... args) ->void
{
// p_function has now been moved into the lambda ...
};
// ... p_function passed to us is now in a valid but undefined state
// so don't use it here
// allow RVO to do its thing
return func;
}
I've come to C++11 from an Objective-C background, and one thing I'm struggling to come to terms with is the different capturing semantics of C++11 lambdas vs Objective-C "blocks". (See here for a comparison).
In Objective-C, like C++, the self/this pointer is implicitly captured if you refer to a member variable. But because all objects in Objective-C are effectively "shared pointers", to use the C++ terminology, you can do this:
doSomethingAsynchronously(^{
someMember_ = 42;
});
... and you're guaranteed that the object whose member you're accessing will be alive when the block executes. You don't have to think about it. The equivalent in C++ seems to be something like:
// I'm assuming here that `this` derives from std::enable_shared_from_this and
// is already owned by some shared_ptr.
auto strongThis = shared_from_this();
doSomethingAsynchronously([strongThis, this] {
someMember_ = 42; // safe, as the lambda holds a reference to this
// via shared_ptr.
});
Here, you need to remember to capture the shared_ptr in addition to the this pointer. Is there some less error-prone way of achieving this?
One of the founding principles of C++ is that you don't pay for what you don't use. That means in this case that contexts where taking a shared_ptr to this is unnecessary shouldn't incur any reference counting overhead. This also means that it shouldn't happen automatically even e.g. as a feature of enable_shared_from_this, since you might want to pass a short-lived lambda to an algorithm (for_each, etc.) in which case the lambda doesn't outlive its scope.
I'd suggest adapting the lambda-wrapper pattern; in that case it's used for move capture of a large object (How to capture std::unique_ptr "by move" for a lambda in std::for_each), but it can equally be used for shared capture of this:
template<typename T, typename F>
class shared_this_lambda {
std::shared_ptr<T> t; // just for lifetime
F f;
public:
shared_this_lambda(std::shared_ptr<T> t, F f): t(t), f(f) {}
template<class... Args>
auto operator()(Args &&...args)
-> decltype(this->f(std::forward<Args>(args)...)) {
return f(std::forward<Args>(args)...);
}
};
template<typename T>
struct enable_shared_this_lambda {
static_assert(std::is_base_of<std::enable_shared_from_this<T>, T>::value,
"T must inherit enable_shared_from_this<T>");
template<typename F>
auto make_shared_this_lambda(F f) -> shared_this_lambda<T, F> {
return shared_this_lambda<T, F>(
static_cast<T *>(this)->shared_from_this(), f);
}
template<typename F>
auto make_shared_this_lambda(F f) const -> shared_this_lambda<const T, F> {
return shared_this_lambda<const T, F>(
static_cast<const T *>(this)->shared_from_this(), f);
}
};
Use by inheriting enable_shared_this_lambda in addition to enable_shared_from_this; you can then explicitly request that any long-lived lambdas take a shared this:
doSomethingAsynchronously(make_shared_this_lambda([this] {
someMember_ = 42;
}));
Boost uses:
auto self(shared_from_this());
auto l = [this, self] { do(); };
Mentioned here: What's the reason of using auto self(shared_from_this()) variable in lambda function?
Actually, there's one right answer to this problem. The answer has the exact same effect of binding with shared_from_this() (like when you do it with boost::asio::io_service). Think about it; what does binding with shared_from_this() do? It simple replaces this. So what prevents you from replacing this with shared_from_this() totally?
Following your example, which I updated to make the difference clearer, instead of this:
auto strongThis = shared_from_this();
doSomethingAsynchronously([strongThis, this] () {
this->someMember_ = 42; //here, you're using `this`... that's wrong!
});
Do this:
auto strongThis = shared_from_this();
doSomethingAsynchronously([strongThis] () //notice, you're not passing `this`!
{
strongThis->someMember_ = 42;
});
The only cost here is that you're gonna have to prefix everything with strongThis->. But this is the most meaningful way to do it.