Closed bennywhipple closed 5 years ago
It seems that your callback is using the technique used by libuv such that you have to specify a callback with a fixed signature that allows you to pass a custom argument through a void*
pointer, which is then castable to your private data (the continuable promise in this case).
For the continuable library this isn't an ideal case because you will have to move the promise to the heap as following (without being capable of elliding the allocation through small buffer optimization):
typedef void(CallbackFn)(void* context, void*, void*);
int async_call(const char* param, CallbackFn cb, void* privateData,
const char* qformat, ...) {
//
return 0;
}
auto my_async_call(const char* param, const char* qformat, ...) {
// handle the varargs in front
// assuming that param stays alive
return cti::make_continuable<void>([param](auto&& promise) {
using type_t = std::decay_t<decltype(promise)>;
type_t* heap_promise = new type_t(std::forward<decltype(promise)>(promise));
async_call(
param,
[](void* context, void*, void*) {
// A lambda without any capture is convertible to a function pointer
std::unique_ptr<type_t> ptr(static_cast<type_t*>(context));
ptr->set_value(/*set the result here*/);
},
heap_promise, ""); // Order probably not correct
});
}
Probably it is easier here to create the callback for this directly rather than wrapping the calling function through promisify<>::from
.
This C-style technique is not ideal from using it out of C++, because you loose a lot of benefits C++ offers, for instance if the callback is never executed you will leak the callback memory here. Also type safety is ignored completely here (this is based on the callback style rather than the library and libuv for instance is affected by those issues).
For the varargs you have to store them in front before creating the continuable because they are usually passed on the stack and don't work well with the lazy evaluation technique used by continuable.
Perhaps I'm wrong, but my impression is that your framework is aimed at efficient type/memory management and Asio's interface is more suited to this than the one I'm using.. so I will take a look at it. Thanks for your help.
@Naios
I would like to convert a function with the following signature into a continuable:
typedef void (CallbackFn)(struct CallbackContext , void , void ); int async_call(const char param, CallbackFn cb, void privateData, const char qformat, ...);
The closest example I've found is the promisify::from example in the tutorial but promisify wants the callback to have a different signature. It would also be nice to retain the varargs in the top-level call but perhaps it is difficult. I like the design of your interface and it would fit in nicely to my project but the template error messages can be daunting.
Any help appreciated - hopefully it is of interest to other users of your library, thanks!