Hi Johannes,
I think the right thing to do is to *return* the new promise, forming a
promise chain.
kj::Promise<void> loop() {
callback();
return timer.afterDelay(period).then([this]() {
return loop();
});
}
The promise framework properly optimizes these "tail calls" such that they
don't leak memory.
BTW, the KJ async framework is also designed to be able to operate on top
of some other event loop. For example, we made it work on top of libuv in
our Node.js bindings -- see the first part of this file:
https://github.com/kentonv/node-capnp/blob/node4/src/node-capnp/capnp.cc
-Kenton
On Fri, Jan 27, 2017 at 3:26 AM, Johannes Zeppenfeld <[email protected]>
wrote:
> I really like the promise-based RPC capabilities provided by capnproto,
> and am working to integrate them into an event-driven application that was
> previously using libev.
>
> Luckily, the application was already using libev-agnostic callback wrapper
> classes for various event types, making it very easy to throw out libev
> code and to replace it with kj. For example, here is the existing interface
> of a periodic callback:
>
> // Callback type called periodically.
> class EventSystem::PeriodicCallback {
> public:
> // Construct a callback to function with the specified period.
> template <typename T_Func>
> PeriodicCallback(double seconds, T_Func &&function);
> ~PeriodicCallback();
>
> // Change the period of the callback.
> void setPeriod(double seconds);
>
> // Enable or disable the callback.
> void enable();
> void disable();
>
> private:
> // Allocate and initialize the implementation structure.
> void _initialize();
>
> private:
> std::function<void()> _function;
> void *_impl;
> };
>
> I have however run into a problem regarding callbacks rescheduling
> themselves, and would like to know what the "recommended" solution is. The
> kj implementation struct for the periodic callback currently looks like so:
>
> struct PeriodicCallbackImpl {
> PeriodicCallbackImpl();
>
> kj::Promise<void> promise;
> kj::Duration period;
> };
>
> Since a promise can only execute once (please correct me if I'm wrong),
> the callback has to reschedule the promise within itself. However, the new
> promise has to be stored somewhere, and the only place to store it is
> within the implementation struct. This however destroys the original
> promise, which is still executing, resulting in an exception: expected
> !firing; Promise callback destroyed itself.
>
> I've come up with two methods that work, but don't quite feel right:
> 1) Add a second promise to the implementation struct, and move the
> executing promise there (requires another promise that is only used
> transiently).
> 2) Call detach on the executing promise (is this legal within the callback
> itself? What is the error handler for in this case?).
>
> What is the recommended method for rescheduling a promise during its own
> callback execution?
>
> --
> You received this message because you are subscribed to the Google Groups
> "Cap'n Proto" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> Visit this group at https://groups.google.com/group/capnproto.
>
--
You received this message because you are subscribed to the Google Groups
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.