0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-02 18:18:56 +02:00

ircd::json::stack: Handle and properly propagate flusher exception out of stack.

This commit is contained in:
Jason Volk 2018-04-13 15:15:45 -07:00
parent 0b217b3474
commit dd69acbad3
2 changed files with 44 additions and 1 deletions

View file

@ -49,10 +49,12 @@ struct ircd::json::stack
window_buffer buf;
flush_callback flusher;
std::exception_ptr eptr;
object *co {nullptr}; ///< The root object instance.
array *ca {nullptr}; ///< Could be union with top_object but
void rethrow_exception();
void append(const size_t &expect, const window_buffer::closure &);
void append(const string_view &);

View file

@ -426,6 +426,7 @@ ircd::json::stack::stack(stack &&other)
noexcept
:buf{std::move(other.buf)}
,flusher{std::move(other.flusher)}
,eptr{std::move(other.eptr)}
,co{std::move(other.co)}
,ca{std::move(other.ca)}
{
@ -451,7 +452,11 @@ ircd::json::stack::append(const string_view &s)
void
ircd::json::stack::append(const size_t &expect,
const window_buffer::closure &closure)
try
{
if(unlikely(eptr))
return;
if(expect > buf.remaining())
{
if(unlikely(!flusher)) throw print_error
@ -462,7 +467,9 @@ ircd::json::stack::append(const size_t &expect,
size(buf.base)
};
flush();
if(!flush())
return;
if(unlikely(expect > buf.remaining())) throw print_error
{
"Insufficient flush. I still need %zu more bytes to buffer.",
@ -478,13 +485,29 @@ ircd::json::stack::append(const size_t &expect,
if(!buf.remaining())
flush();
}
catch(...)
{
assert(!this->eptr);
this->eptr = std::current_exception();
}
void
ircd::json::stack::rethrow_exception()
{
if(unlikely(eptr))
std::rethrow_exception(eptr);
}
bool
ircd::json::stack::flush()
try
{
if(!flusher)
return false;
if(unlikely(eptr))
return false;
// The user returns the portion of the buffer they were able to flush
// rather than forcing them to wait on their sink to flush the whole
// thing, they can continue with us for a little while more.
@ -497,11 +520,18 @@ ircd::json::stack::flush()
buf.shift(size(flushed));
return true;
}
catch(...)
{
assert(!this->eptr);
this->eptr = std::current_exception();
return false;
}
void
ircd::json::stack::clear()
{
buf.rewind(buf.consumed());
this->eptr = std::exception_ptr{};
}
ircd::const_buffer
@ -574,6 +604,8 @@ ircd::json::stack::object::object(member &pm)
,pm{&pm}
{
assert(s->opened());
s->rethrow_exception();
assert(pm.co == nullptr);
assert(pm.ca == nullptr);
pm.co = this;
@ -585,6 +617,8 @@ ircd::json::stack::object::object(array &pa)
,pa{&pa}
{
assert(s->opened());
s->rethrow_exception();
assert(pa.co == nullptr);
assert(pa.ca == nullptr);
pa.co = this;
@ -666,6 +700,8 @@ ircd::json::stack::array::array(member &pm)
,pm{&pm}
{
assert(s->opened());
s->rethrow_exception();
assert(pm.co == nullptr);
assert(pm.ca == nullptr);
pm.ca = this;
@ -677,6 +713,8 @@ ircd::json::stack::array::array(array &pa)
,pa{&pa}
{
assert(s->opened());
s->rethrow_exception();
assert(pa.co == nullptr);
assert(pa.ca == nullptr);
pa.ca = this;
@ -781,6 +819,9 @@ ircd::json::stack::member::member(object &po,
,po{&po}
,name{name}
{
assert(s->opened());
s->rethrow_exception();
assert(po.cm == nullptr);
po.cm = this;