Since we have lots of queues, we need an efficient queue structure,
esp. for moveable types. libstdc++'s std::deque is quite hairy,
and boost's circular_buffer_space_optimized uses assignments instead of
constructors, which are both slower and less available than constructors.
This patch implements a growable circular buffer for these needs.
Here, transferring is defined as moving an object to a new location
(either via a move or copy constructor) and destroying the source. This
is useful when implementing containers.
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
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.
It allows for simpler client code because the client can assume that
when cancel() returns the callback will not run and thus there's no
need to handle the race between timer teardown and execution of the
callback.
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.
Fix error with tcp_test:
terminate called after throwing an instance of
'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_any_cast> >'
what(): boost::bad_any_cast: failed conversion using boost::any_cast
This method, intended for request parsers, receives a stream of temporary
buffers until it determines that parsing is done, at which point it can
return any unconsumed partial buffer back to the input stream.
It is intended as a replacement for read_until(), since it can parse in a
single pass.
Runing on pre-glibc2.18 hosts (like C7) is impossible without this. The
downside is that the developer has to download, build, and install static
versions of libtcmalloc and libaio.
timer_set maintains next timeout so no need to duplicate it.
This also fixes a potential issue, if upon timer expiry no timer is
pending we did not update _next_timeout which will result in timer fd
not being updated upon next arm().