mirror of
https://github.com/matrix-construct/construct
synced 2024-12-25 23:14:13 +01:00
ircd::json::stack: Handle and properly propagate flusher exception out of stack.
This commit is contained in:
parent
0b217b3474
commit
dd69acbad3
2 changed files with 44 additions and 1 deletions
|
@ -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 &);
|
||||
|
||||
|
|
43
ircd/json.cc
43
ircd/json.cc
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue