Commit Graph

42 Commits

Author SHA1 Message Date
Gleb Natapov
0838a0ce2f core: drop future<> casting to rvalue before call to then_wrapped()
No longer required.
2015-03-11 17:19:23 +02:00
Gleb Natapov
4d286f0504 core: drop superfluous qualifier from then_wrapped 2015-03-06 12:52:11 +02:00
Tomasz Grabiec
af82e23c75 core: Use futurize<> to unify then_wrapped() specializations 2015-03-06 11:35:56 +01:00
Tomasz Grabiec
a232b7e6c5 core: Use futurize<> to unify future::then() specializations
As a side benefit, returning non-void non-future is now allowed:

 future<int> x() {
     return later().then([] {
         return 3;
     });
 }
2015-03-06 11:35:56 +01:00
Tomasz Grabiec
f25d7ac068 core: Add futurize::apply()
Invokes given function wrapping the result in a future if necessary.
2015-03-06 11:35:56 +01:00
Tomasz Grabiec
422d642cf4 core: Add futurize::primise_type 2015-03-06 11:35:56 +01:00
Tomasz Grabiec
f5485c667d core: Move futurize<> to future.hh 2015-03-06 11:35:56 +01:00
Tomasz Grabiec
83963b23d3 Replace rescue() usages with then_wrapped()
They are pretty much the same. This change removes rescue().
2015-03-04 17:34:59 +01:00
Tomasz Grabiec
e36115e1d4 core: add then_wrapped() overload which works with void-returning callbacks 2015-03-04 17:33:38 +01:00
Calle Wilund
7b5193b80c future: deferring finally() callback
Add "finally" continuation overload for functions returning future type that
awaits finishing the continuation in question before continuing the "present"
one. I.e. a wrapper around "then_wrapped" to remove the need to deal with the
original return value.

Signed-off-by: Calle Wilund <calle@cloudius-systems.com>
2015-03-04 18:09:34 +02:00
Gleb Natapov
590d8da4f1 core: provide "void" promise specialization
Makes it easier to write generic code.
2015-03-01 15:58:36 +02:00
Nadav Har'El
b64f26832e reactor: terminate cleanly in or_terminate()
The ".or_terminate()" continuation is needed when one needs to exit the
application on an unhandled exception, instead of just letting the event
loop continue to spin forever.

or_terminate() currently calls std::terminate() which only incidentally
(as a gcc-specific implementation) prints out the exception's type; It
then calls abort(), which results in a painfully slow core dump. This
abort() is NOT helpful, because at that point the debugger can only find
where abort() was called, not where the original exception was thrown (see
issue #32).

So instead of calling std::terminate(), this patch switches to calling
engine().exit(), to cleanly shut down the application, without dumping
core. It also prints, like gcc's std::terminate(), the exception's type.
This printing requires non-standard gcc extensions.

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
2015-02-25 12:28:34 +02:00
Avi Kivity
7f8d88371a Add LICENSE, NOTICE, and copyright headers to all source files.
The two files imported from the OSv project retain their original licenses.
2015-02-19 16:52:34 +02:00
Avi Kivity
e746eb7f84 future: fix make_exception_future build error
Add missing std::.
2015-01-15 15:19:02 +02:00
Avi Kivity
311e1c834e future: fix future::then_wrapped() in exception case
Calling state.get() will throw the exception instead of calling the function,
thus denying the called function the chance to deal with the exception.

Fix by constructing the future directly from state.
2015-01-15 15:19:02 +02:00
Avi Kivity
7dfd7de8cd future: optimize data-less future<>
A future that does not carry any data (future<>) and its sibling (promise<>)
are heavily used in the code.  We can optimize them by overlaying the
future's payload, which in this case can only be an std::exception_ptr,
with the future state, as a pointer and an enum have disjoint values.

This of course depends on std::exception_ptr being implemented as a pointer,
but as it happens, it is.

With this, sizeof(future<>) is reduced from 24 bytes to 16 bytes.
2014-12-09 10:08:48 +02:00
Tomasz Grabiec
b6511ce3f4 core: add future::discard_result()
Use when you don't want to care about the result and just want to
return a future<>.

The current implementation may not be the most optimal way to do it
but it can be improved later if there's need.
2014-11-09 16:33:34 +02:00
Gleb Natapov
e5dfd8e863 future: limit number of ready futures that are executed without scheduling a task
Otherwise stack may overflow if a very long chain of ready futures is
executed.
2014-11-04 15:18:32 +02:00
Avi Kivity
3d414111eb future: make .rescue() require an rvalue reference for its future
This makes it harder to misuse.
2014-10-30 14:07:42 +02:00
Avi Kivity
c4bc67414e future: add then_wrapped()
Unlike future::then(), which unwraps the value, then_wrapped() keeps it
wrapped in a future<>, so if it is exceptional, it can still be accessed.

This is similar to the proposed std::future::then(), so we should later
rename it to match (and rename the existing future::then() to future::next().
2014-10-30 13:55:31 +02:00
Tomasz Grabiec
eb84a3b78b core: fix future::forward_to()
It did not handle properly the case when the target promise's future gets dead
without installing a callback or the future was never installed. The
mishanlding of the former case was causing httpd to abort on SMP.
2014-10-27 15:58:57 +02:00
Avi Kivity
0d745abf69 future: sprinke noexcept everywhere
When used correctly, noexcept allows containers to optimize their reallocation
code.
2014-10-26 14:34:56 +02:00
Tomasz Grabiec
74ac65a491 core: optimize future::forward_to()
We can avoid extra allocation and chaining by linking the current
future's promise with the target promise's future, as if the target
promise was moved into the current future's promise.
2014-10-24 19:40:48 +03:00
Tomasz Grabiec
ca077f33ef core: introduce or_terminate()
Calls std::terminate() when future fails. It can be used like this:

  do_something([] {}).or_terminate();
2014-10-15 15:59:41 +02:00
Tomasz Grabiec
cf7a084457 core: move some of the networking abstractions to net/api.hh 2014-10-06 18:34:28 +02:00
Avi Kivity
ef96af29f2 future: avoid generalized lambda in forward_to()
Crashes gdb with -O0.
2014-10-05 15:44:49 +03:00
Tomasz Grabiec
6fa9cd7ac9 core: introduce do_until() and keep_doing() 2014-10-04 11:27:23 +02:00
Tomasz Grabiec
6fa3212888 core: fix missing error propagation when intermediate future is involved
Test case (added in the next patch):

    promise<> p1;
    promise<> p2;

    auto f = p1.get_future().then([f = std::move(p2.get_future())] () mutable {
        return std::move(f); // this future will fail
    }).then([] {
        // never reached, that's ok
    });

    p1.set_value();
    p2.set_exception(std::runtime_error("boom"));

    // f should get resolved eventually with error, but was not
2014-10-01 13:45:28 +02:00
Tomasz Grabiec
d9bf08c1b3 core: introduce future::finally()
The callback passed to it will be executed when future gets resolved,
successfully or not. The returned future will mimic the state of the
target future.
2014-10-01 13:45:28 +02:00
Tomasz Grabiec
fcb55c1f04 core: introduce future::forward_to()
It causes that when future is resolved, the target promise will be
resolved too with the same state.
2014-10-01 13:45:28 +02:00
Tomasz Grabiec
07d6df11a8 core: introduce make_exception_future() which works with exception objects 2014-10-01 13:45:25 +02:00
Tomasz Grabiec
125a696d6c core: introduce promise::set_exception() which works with exception objects 2014-10-01 13:45:22 +02:00
Tomasz Grabiec
eeea3640f2 core: make future::rescue() return a future<>
This will allow to compose rescue() just like then().
2014-10-01 13:21:09 +02:00
Tomasz Grabiec
5f2e06beda core: make future's result obtainable via future::rescue()
This will allow the user to have one handler for both success and
failure. This simplifies client code a bit when both paths need to
work on the same object. Having to split the function into two
callbacks, one of which is passed to then() and the other to rescue()
on a resulting promise, would make it necessary to wrap the object in
a shared_ptr, which is suboptimal.
2014-10-01 13:21:02 +02:00
Tomasz Grabiec
9816422a67 core: fix SIGSEGV in future::then()
This fixes SIGSEGV which happens when a promise gets resolved and
dies before the callback is registerred via then(). The latter assumes
that _promise must not be nullptr if the state is not resolved
yet. The dying promise should move the resolved state into the
future's local state.
2014-09-22 23:11:13 +03:00
Avi Kivity
3b1d37ff2f future: implement available()
As the whole point of future/promise is to decouple the producer from the
consumer, available() is not generally useful.  However it can still be
useful in special cases when we want to know who got there first.

One of them is deciding when to drop packets -- if the consumer is not
ready, and no queue space is available, we should just drop the packet
instead of waiting for the consumer.
2014-09-22 11:25:54 +03:00
Avi Kivity
1d11ecfbcd future: implement move assignment 2014-09-22 11:25:54 +03:00
Avi Kivity
64ce457053 future: fix move constructor
If we're no longer tracking the promise (either gone, or never existed),
we shouldn't update it.
2014-09-22 11:25:54 +03:00
Avi Kivity
f7a0a3cdc6 future: reduce allocations
Instead of keeping the future state in heap storage, referenced from
the promise/future/task, keep the state in the promise or future and only
allocate it on the heap as a last resort (for a stack).

Improves httpd throughtput by ~20%.
2014-09-15 14:31:58 +03:00
Avi Kivity
1385a5278e core: get rid of embarassing while () loop in future_state::get() 2014-09-09 12:37:13 +03:00
Avi Kivity
12aba7e9cb core: fix promise move assignment
Leaked if an object was assigned to itself.
2014-09-08 21:00:09 +03:00
Avi Kivity
300abc77d8 core: split future/promise into a new header file 2014-09-04 10:37:59 +03:00