0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-27 07:54:05 +01:00

ircd: Add exception tools which elide copying.

This commit is contained in:
Jason Volk 2019-03-16 15:01:46 -07:00
parent e752070d06
commit cff17eaa40
6 changed files with 61 additions and 38 deletions

View file

@ -41,6 +41,7 @@ namespace ircd
std::system_error make_system_error(const boost::system::system_error &); std::system_error make_system_error(const boost::system::system_error &);
template<class... args> std::exception_ptr make_system_eptr(args&&...); template<class... args> std::exception_ptr make_system_eptr(args&&...);
template<class... args> [[noreturn]] void throw_system_error(args&&...); template<class... args> [[noreturn]] void throw_system_error(args&&...);
template<class E, class... args> std::exception_ptr make_exception_ptr(args&&...);
string_view string(const mutable_buffer &, const std::error_code &); string_view string(const mutable_buffer &, const std::error_code &);
string_view string(const mutable_buffer &, const std::system_error &); string_view string(const mutable_buffer &, const std::system_error &);
@ -221,6 +222,19 @@ namespace ircd
IRCD_PANICKING(panic, not_implemented) IRCD_PANICKING(panic, not_implemented)
} }
template<class E,
class... args>
std::exception_ptr
ircd::make_exception_ptr(args&&... a)
try
{
throw E{std::forward<args>(a)...};
}
catch(const E &)
{
return std::current_exception();
};
template<class... args> template<class... args>
void void
ircd::throw_system_error(args&&... a) ircd::throw_system_error(args&&... a)

View file

@ -43,7 +43,7 @@ struct ircd::server::tag
std::unique_ptr<char[]> cancellation; std::unique_ptr<char[]> cancellation;
void set_exception(std::exception_ptr); void set_exception(std::exception_ptr);
template<class... args> void set_exception(args&&...); template<class T, class... args> void set_exception(args&&...);
template<class... args> void set_value(args&&...); template<class... args> void set_value(args&&...);
const_buffer make_write_content_buffer() const; const_buffer make_write_content_buffer() const;

View file

@ -2039,16 +2039,20 @@ noexcept
} }
ircd::ctx::promise_base::~promise_base() ircd::ctx::promise_base::~promise_base()
noexcept noexcept try
{ {
if(!valid()) if(!valid())
return; return;
if(refcount(state()) == 1) if(refcount(state()) == 1)
set_exception(std::make_exception_ptr(broken_promise())); throw broken_promise{};
else else
remove(state(), *this); remove(state(), *this);
} }
catch(const std::exception &e)
{
set_exception(std::current_exception());
}
void void
ircd::ctx::promise_base::set_exception(std::exception_ptr eptr) ircd::ctx::promise_base::set_exception(std::exception_ptr eptr)

View file

@ -311,10 +311,7 @@ ircd::server::cancel(request &request)
}; };
*/ */
tag.set_exception(canceled tag.set_exception<canceled>("Request canceled");
{
"Request canceled"
});
// We got off easy... The link's write loop won't start an abandoned // We got off easy... The link's write loop won't start an abandoned
// request. All that has to be done is indicate a full cancellation // request. All that has to be done is indicate a full cancellation
@ -414,10 +411,10 @@ void
ircd::server::peer::cancel() ircd::server::peer::cancel()
{ {
for(auto &link : this->links) for(auto &link : this->links)
link.cancel_all(std::make_exception_ptr(canceled link.cancel_all(make_exception_ptr<canceled>
{ (
"Request was aborted due to interruption." "Request was aborted due to interruption."
})); ));
} }
bool bool
@ -503,10 +500,10 @@ try
"No link to peer %s available", hostcanon "No link to peer %s available", hostcanon
}; };
else else
request.tag->set_exception(unavailable request.tag->set_exception<unavailable>
{ (
"No link to peer %s available", hostcanon "No link to peer %s available", hostcanon
}); );
} }
catch(const std::exception &e) catch(const std::exception &e)
{ {
@ -854,10 +851,10 @@ void
ircd::server::peer::disperse(link &link) ircd::server::peer::disperse(link &link)
{ {
disperse_uncommitted(link); disperse_uncommitted(link);
link.cancel_committed(std::make_exception_ptr(canceled link.cancel_committed(make_exception_ptr<canceled>
{ (
"Request was aborted; though it was partially completed" "Request was aborted; though it was partially completed"
})); ));
assert(link.queue.empty()); assert(link.queue.empty());
} }
@ -1738,9 +1735,9 @@ try
assert(done || empty(overrun)); assert(done || empty(overrun));
return overrun; return overrun;
} }
catch(const buffer_overrun &e) catch(const buffer_overrun &)
{ {
tag.set_exception(e); tag.set_exception(std::current_exception());
throw; throw;
} }
@ -2573,13 +2570,13 @@ ircd::server::tag::read_content(const const_buffer &buffer,
if(content_overflow() && !req.opt->truncate_content) if(content_overflow() && !req.opt->truncate_content)
{ {
assert(state.content_read > size(content)); assert(state.content_read > size(content));
set_exception(buffer_overrun set_exception<buffer_overrun>
{ (
"buffer of %zu bytes too small for content-length %zu bytes by %zu bytes", "buffer of %zu bytes too small for content-length %zu bytes by %zu bytes",
size(content), size(content),
state.content_length, state.content_length,
content_overflow() content_overflow()
}); );
} }
else set_value(state.status); else set_value(state.status);
} }
@ -3309,21 +3306,30 @@ ircd::server::tag::set_value(args&&... a)
data(request->in.content), size(request->in.content) data(request->in.content), size(request->in.content)
}; };
set_exception(http::error{code, std::string{content}}); set_exception<http::error>(code, std::string{content});
return; return;
} }
p.set_value(code); p.set_value(code);
} }
template<class... args> template<class E,
class... args>
void void
ircd::server::tag::set_exception(args&&... a) ircd::server::tag::set_exception(args&&... a)
try
{ {
if(abandoned()) if(abandoned())
return; return;
set_exception(std::make_exception_ptr(std::forward<args>(a)...)); throw E
{
std::forward<args>(a)...
};
}
catch(const std::exception &e)
{
set_exception(std::current_exception());
} }
void void

View file

@ -65,13 +65,8 @@ ircd::net::dns::handle_ipport__A(callback_ipport_one callback,
const hostport &hp, const hostport &hp,
const rfc1035::record::A &record) const rfc1035::record::A &record)
{ {
static const ircd::net::not_found no_record
{
"Host has no A record"
};
if(!eptr && !record.ip4) if(!eptr && !record.ip4)
eptr = std::make_exception_ptr(no_record); eptr = make_exception_ptr<not_found>("Host has no A record");
const ipport ipport const ipport ipport
{ {

View file

@ -101,10 +101,12 @@ ircd::net::dns::cache::_get(const hostport &hp,
//TODO: we don't cache what the error was, assuming it's //TODO: we don't cache what the error was, assuming it's
//TODO: NXDomain can be incorrect and in bad ways downstream... //TODO: NXDomain can be incorrect and in bad ways downstream...
static const auto rcode{3}; //NXDomain static const auto rcode{3}; //NXDomain
eptr = std::make_exception_ptr(rfc1035::error eptr = make_exception_ptr<rfc1035::error>
{ (
"protocol error #%u (cached) :%s", rcode, rfc1035::rcode.at(rcode) "protocol error #%u (cached) :%s",
}); rcode,
rfc1035::rcode.at(rcode)
);
} }
if(count < record.size()) if(count < record.size())
@ -143,10 +145,12 @@ ircd::net::dns::cache::_get(const hostport &hp,
//TODO: we don't cache what the error was, assuming it's //TODO: we don't cache what the error was, assuming it's
//TODO: NXDomain can be incorrect and in bad ways downstream... //TODO: NXDomain can be incorrect and in bad ways downstream...
static const auto rcode{3}; //NXDomain static const auto rcode{3}; //NXDomain
eptr = std::make_exception_ptr(rfc1035::error eptr = make_exception_ptr<rfc1035::error>
{ (
"protocol error #%u (cached) :%s", rcode, rfc1035::rcode.at(rcode) "protocol error #%u (cached) :%s",
}); rcode,
rfc1035::rcode.at(rcode)
);
} }
if(count < record.size()) if(count < record.size())