What is the syntax to create heap allocated closure manage by shared_ptr. I want to pass closures to functions and be able to pass nullptr. Seems like using a shared_ptr< ::std::function<void()> but I cannot figure the syntax to initialize that from a lambda expresion
It should be something like
auto lambda = []() { /* do something usefull */ };
auto p = std::make_shared<std::function<void()>>(lambda);
But actually you may no need shared_ptr, since function can be constructed from nullptr.
std::function<void()> fnc(nullptr);
Generally speaking, you want to create a shared_ptr<X> via make_shared, initializing the X object with some Y object. Then generally the code to do that is
auto ptr = make_shared<X>(someY);
In your case, X is the std::function type, and the someY is your lambda. Once you have that, it's pretty straight forward:
auto funPtr = std::make_shared<function<void()>>( [](){ std::cout << "Hello World!\n"; } );
(*funPtr)();
You can do it in two ways:
std::function<void()> lambda = [](){};
auto heapPtr = std::make_shared<std::function<void()>>(lambda);
auto heapPtr2 = new std::function<void()>(lambda);
You might also find the following questions useful:
C++11 lambda implementation and memory model
In C++11 lambda syntax, heap-allocated closures?
I prefer putting shared_ptr inside the function object.
auto o = make_shared<MyData>();
return [o] ()
{
...
};
So, the data for the closure is on the heap and ref-counted while the handle can be copied and passed around. The data is cleaned up when the last handle is destroyed.
Related
I have an class job. I want to create a unique_ptr of job, capture it in a lamdba and execute a function in a lambda which forwards this pointer:
The function:
void printJob(std::unique_ptr<job> aJob)
Lamdba:
auto jobptr = std::make_unique<job>(<arguments>);
auto function = [this, j = std::move(jobptr)]
{
printJob(j);
};
The function is executed on a different thread therefor the lamdba is used
The j argument in the lamdba is of type std::remove_reference_t<std::unique_ptr<job> &> while the function need a std::unique_ptr<job>. Can I make this work? Tried options with std::move and std::forward but I cant get it to compile. I am using C++14.
I have found alternatives (shared_ptr, raw pointer, etc) but this is more in sync with the existing code.
If printJob's parameter is a std::unique_ptr<job> then it must be passed in via move semantics, via std::move itself.
Captured objects in regular lambdas are, effectively, const object, hence they are not movable. The solution is simple: use a mutable lambda.
auto function = [this, j = std::move(jobptr)]
mutable {
printJob(std::move(j));
};
It goes without saying that this lambda can only be effectively executed just once.
But does printJob really need to take ownership of the passed in parameter? If not, if it's just as happy as
void printJob(const std::unique_ptr<job> &aJob)
then none of this is needed.
I have a piece of code which calls an async rdma-write. The rdma API receives a void* context which I would like to use to pass a callback to be called when the operation finishes.
void invoke_async_operation(... some stuff to capture ...) {
...
MyCallBackType* my_callback = // Create callback somehow
rdma_post_write(..., my_callback);
...
}
void on_complete(void* context) {
(*(MyCallbackType*)context)();
}
I thought using a lambda here would be best, because it will easily capture all the context which is required to the later callback invokement. However I saw in What is the lifetime of a C++ lambda expression? that a lambda lifetime is limited to the scope where it was defined.
Note that I can't copy the lambda, because context is a pointer.
What is the correct approach here? Should I insist on using lambdas and prolong their lifetime somehow, or is there a better way? Thanks.
Lifetime of a lambda
The object that represents the lamda expression and allows to invoke it, obeys indeed the usual scoping rules.
However this object can be copied (e.g passing it as argument to a function or a constructor, or assigning it to a global, or whatever else you want to do) so that the lambda can be invoked at any later point, even after the scope it was initially defined in is left.
Because of exactly this potentially long survival of lambdas, you can find quite a few questions, blogs or books that will advise on careful use of the lambda capture, especially if captured by reference, because the lambda itself (and not its anonymous proxy object) can be called even after the referred objects are destroyed.
Your callback issue
You are constraint in your design by the use of an OS callback that can only convey a raw pointer that was passed to it when the callback was set up.
The way to approach this could be to use a std::function object of the standard <functional> library. Here a small function to show you how it works:
function<void()>* preparatory_work() {
auto l = [](){ cout<< "My lambda is fine !" <<endl; } ; // lambda
function<void ()> f = l; // functor
auto p = new function<void()>(l); // a functor on the heap
l(); // inovke the lambda object
f(); // invoke the functor
(*p)(); // invoike functor via a pointer
return p;
}
Function objects are as handy to use as any other object and as easy to declare as function pointers. They are however much more powerful than function pointers, because they can refer basically to any callable object.
As you see, in the example above, I allocated a function objet with new, and returned its pointer. So you could indeed later invoke this function:
int main() {
auto fcp = preparatory_work(); // fcp is a pointer
(*fcp)();
// and even with casting as you would like
void *x = (void*)fcp;
(*(function<void()>*)x)(); // YES !!!
}
Here an online demo
I'm trying to make a function that accepts a shared pointer to some functor. With manually crafted functors there're no problems, but with lambda there are. I know that I can't use decltype with lambda - every new lambda declaration creates a new type. Right now I'm writing:
auto lambda = [](int a, float b)->int
{
return 42;
};
using LambdaType = decltype(lambda);
shared_ptr<LambdaType> ptr{ new LambdaType{ lambda } };
It works, but looks ugly. Moreover there's a copy constructor call! Is there any way to simplify?
You could use std::function as type.
Lambdas are merely auto written invokable objects to make simple code simple. It you want something beyond their default automatic storage behavior, write the type they write yourself.
It is illegal to have a lambda type in an unevaluated context. In an evaluated context, it creates a lambda in automatic storage. You want it on the free store. This requires at least logically a copy.
A horrible hack involving violating the unevaluated context rule, sizeof/alignof, aligned_storage_t, placement new, possibly unbounded compile time recursion (or maybe one with a static_assert), returning pointers to local variables, and the aliasing constructor of shared ptr, and requiring callers to write insane code might avoid calling the copy/move. But it is a bad idea, and simply using invokable objects is easier.
Of course, accepting the copy/move makes it trivial. But at that point, just use std::function unless you need something like varargs.
You state you do not want to force users to use std::function; but std::function would implicitly convert a compatible lambda into itself.
If you are willing to accept a copy, we can do this:
template<class T>
std::shared_ptr<std::decay_t<T>>
auto_shared( T&& t ) {
return std::make_shared<std::decay_t<T>>(std::forward<T>(t));
}
then auto ptr = auto_shared( [x=0]()mutable{ return x++; } ); is a non-type-erased shared pointer to a counting lambda. The lambda is copied (well, moved) into the shared storage.
If you want to avoid that copy, the client can write a manual function object and call make_shared<X>(ctor_args) on it.
There is no reasonable way to separate a lambdas type from its construction in C++ at this point.
if you catch something in lambda, it becomes algorithmically same as std::function, so use it freely. Also, std::function implements captured values memory management, so using std::shared_ptr on top of it is not required.
If you catch nothing, lambda is convertible to simple function pointer:
int(*ptr)(int,int) = [](int a, int b) -> int {
return a+b;
};
Functions are allocated statically and definitely shouldn't be deleted. So, you don't actually need std::shared_ptr
For the struct:
struct A {
int var = 10;
void check() {
std::cout << "var is " << var << std::endl;
}
};
Say I create a std::function object of A::check(), using a dynamically allocated a object:
auto a_ptr = std::make_unique<A>();
std::function<void()> f = std::bind(&A::check, a_ptr.get());
//...later/elsewhere...
f();
It would be nice for safety if I could test f to see if the bound A object is still alive. Is it possible to retrieve that information from f directly? Assume a_ptr is not accessible from the call point, so I can't test against a_ptr directly. Using std::function's operator bool, or testing f against nullptr don't work.
So you basically want your function object to test for the existence of the A instance managed by a_ptr, i see 3 ways of doing this with the current c++ std features.
-- Lambda with a reference to the unique_ptr
auto a_ptr = std::make_unique<A>();
std::function<void()> f = [&] { if (a_ptr) a_ptr->check(); };
//...later/elsewhere...
f();
This requires that the pointer is still alive anytime the function object is alive.
-- Lambda with a copy of the shared_ptr
auto a_ptr = std::make_shared<A>();
std::function<void()> f = [=] { if (a_ptr) a_ptr->check(); };
//...later/elsewhere...
f();
Same thing but without requirements on the lifetime relationship at the expense of some additional performance cost which is mainly the copy of a shared pointer, probably totally worth the headache it saves in most cases (i'm going to be burned by the optimisation guys for this one).
-- Custom deleter in your smart pointer that resets your function
std::function<void()> f;
auto a_ptr = std::unique_ptr<A, std::function<void(A*)>>(new A, [&](A*){ f = nullptr;});
f = std::bind(&A::check, a_ptr.get());
//...later/elsewhere...
a_ptr.reset();
if (f)
f();
This requires that somehow your deleter can access the function to reset it, whether it is directly or through a storage system in your classes (containers of functions are a nice design imo).
You can also create more elaborated systems with your own primitives but that would lead you further away from the standard library. Ultimately you'll have to choose what's best in your situation mainly based on the lifespan and ownership relationships of your objects.
Well, this one is easy, use std::shared_ptr.
when you think about it , you basically want to ensure that some entity in you program is valid as long as something is using it.
In other words, you are looking for a shared_ptr.
Otherwise, the design looks a bit weird, if some single entity in your program is owning a_ptr, it should be the single owner of all the std::functions which uses this resource, which is not your intention. if that owner is not the owner of the std::function you are highly increasing the probability of segmentation faults, heap corruption and other stuff you don't want.
I have a program, where I cannot use the standard std::async and threading mechanisms. Instead I have to code the program like so:
void processor( int argument, std::function<void(int)> callback ) {
int blub = 0;
std::shared_ptr<object> objptr = getObject();
// Function is called later.
// All the internal references are bound here!
auto func = [=, &blub]() {
// !This will fail since blub is accessed by reference!
blub *= 2;
// Since objptr is copied by value it works.
// objptr holds the value of getObject().
objptr->addSomething(blub);
// Finally we need to call another callback to return a value
callback(blub);
};
objptr = getAnotherObject();
// Puts func onto a queue and returns immediately.
// func is executed later.
startProcessing(func);
}
I now would like to know whether I am doing it right or what the best way of using lambdas as asynchronous callbacks is.
EDIT: Added expected behavior to the code comments.
See answer/comments for possible solutions for the problem with blub.
The function object will contain a reference to the local variable blub. As in every other situation in the language, this won't make the local variable live after the function ends.
Copies of all the other captured objects will be stored within the function object, since they're captured-by-value. This means there's no issue with them.
If you want it to live after the function ends, you cannot tie its lifetime to the function: you need dynamic storage duration. A std::unique_ptr can be used to to handle the cleanup of such an object, but it gets a bit annoying because you can't "capture-by-move" into a lambda :S
auto blub = make_unique<int>(0); // [1]
std::shared_ptr<object> objptr = getObject();
// use std::bind to store the unique_ptr with the lambda
auto func = std::bind([=](std::unique_ptr<int>& blub) {
*blub *= 2;
objptr->addSomething(*blub);
callback(*blub);
}, std::move(blub)); // move the unique_ptr into the function object
objptr = getAnotherObject();
// func is not copiable because it holds a unique_ptr
startProcessing(std::move(func)); // move it
As an added note, the old deprecated std::auto_ptr would actually work fine here, because if the lambda captures it by value it gets copied and its strange copy semantics are exactly what's needed.
1. See GOTW #102 for make_unique.