0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-26 07:23:53 +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 &);
template<class... args> std::exception_ptr make_system_eptr(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::system_error &);
@ -221,6 +222,19 @@ namespace ircd
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>
void
ircd::throw_system_error(args&&... a)

View file

@ -43,7 +43,7 @@ struct ircd::server::tag
std::unique_ptr<char[]> cancellation;
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&&...);
const_buffer make_write_content_buffer() const;

View file

@ -2039,16 +2039,20 @@ noexcept
}
ircd::ctx::promise_base::~promise_base()
noexcept
noexcept try
{
if(!valid())
return;
if(refcount(state()) == 1)
set_exception(std::make_exception_ptr(broken_promise()));
throw broken_promise{};
else
remove(state(), *this);
}
catch(const std::exception &e)
{
set_exception(std::current_exception());
}
void
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
{
"Request canceled"
});
tag.set_exception<canceled>("Request canceled");
// 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
@ -414,10 +411,10 @@ void
ircd::server::peer::cancel()
{
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."
}));
));
}
bool
@ -503,10 +500,10 @@ try
"No link to peer %s available", hostcanon
};
else
request.tag->set_exception(unavailable
{
request.tag->set_exception<unavailable>
(
"No link to peer %s available", hostcanon
});
);
}
catch(const std::exception &e)
{
@ -854,10 +851,10 @@ void
ircd::server::peer::disperse(link &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"
}));
));
assert(link.queue.empty());
}
@ -1738,9 +1735,9 @@ try
assert(done || empty(overrun));
return overrun;
}
catch(const buffer_overrun &e)
catch(const buffer_overrun &)
{
tag.set_exception(e);
tag.set_exception(std::current_exception());
throw;
}
@ -2573,13 +2570,13 @@ ircd::server::tag::read_content(const const_buffer &buffer,
if(content_overflow() && !req.opt->truncate_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",
size(content),
state.content_length,
content_overflow()
});
);
}
else set_value(state.status);
}
@ -3309,21 +3306,30 @@ ircd::server::tag::set_value(args&&... a)
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;
}
p.set_value(code);
}
template<class... args>
template<class E,
class... args>
void
ircd::server::tag::set_exception(args&&... a)
try
{
if(abandoned())
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

View file

@ -65,13 +65,8 @@ ircd::net::dns::handle_ipport__A(callback_ipport_one callback,
const hostport &hp,
const rfc1035::record::A &record)
{
static const ircd::net::not_found no_record
{
"Host has no A record"
};
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
{

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: NXDomain can be incorrect and in bad ways downstream...
static const auto rcode{3}; //NXDomain
eptr = std::make_exception_ptr(rfc1035::error
{
"protocol error #%u (cached) :%s", rcode, rfc1035::rcode.at(rcode)
});
eptr = make_exception_ptr<rfc1035::error>
(
"protocol error #%u (cached) :%s",
rcode,
rfc1035::rcode.at(rcode)
);
}
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: NXDomain can be incorrect and in bad ways downstream...
static const auto rcode{3}; //NXDomain
eptr = std::make_exception_ptr(rfc1035::error
{
"protocol error #%u (cached) :%s", rcode, rfc1035::rcode.at(rcode)
});
eptr = make_exception_ptr<rfc1035::error>
(
"protocol error #%u (cached) :%s",
rcode,
rfc1035::rcode.at(rcode)
);
}
if(count < record.size())