mirror of
https://github.com/latentPrion/libspinscale.git
synced 2026-06-23 19:48:32 +00:00
Nursery: Don't pass exceptions to main loop
This commit is contained in:
@@ -190,11 +190,10 @@ nursery.openAdmission();
|
||||
|
||||
auto lease = nursery.getNewSlotLease();
|
||||
lease.getSyncCanceler().startAcceptingWork();
|
||||
std::exception_ptr &exceptionStorage = lease.getExceptionStorage();
|
||||
lease.setOnSettledHook(
|
||||
[&exceptionStorage]()
|
||||
[](std::exception_ptr &exceptionPtr)
|
||||
{
|
||||
sscl::co::NonViralCompletion nvc(exceptionStorage);
|
||||
sscl::co::NonViralCompletion nvc(exceptionPtr);
|
||||
nvc.checkAndRethrowException();
|
||||
});
|
||||
lease.fillSlot(
|
||||
@@ -221,10 +220,9 @@ all slots have retired naturally and throw if admission is still open.
|
||||
`Slot::Lease` is commit-required: an uncommitted lease removes its reservation on
|
||||
destruction. `fillSlot()` takes an invoker factory (deferred construction) because
|
||||
non-viral coroutines may complete synchronously during invoker construction.
|
||||
The factory may capture `lease` by reference; `setOnSettledHook()` may not.
|
||||
The hook runs after the lease is destroyed, so capture slot-owned state such as
|
||||
`lease.getExceptionStorage()` (a reference to the slot's `exceptionPtr`), not
|
||||
`lease` itself.
|
||||
The factory may capture `lease` by reference; `setOnSettledHook()` may not
|
||||
capture `lease` itself. The nursery passes the slot's `exceptionPtr` into the
|
||||
hook at retirement.
|
||||
`Slot::Handle` is an opaque slot pointer valid only while the slot remains in the
|
||||
nursery.
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
@@ -116,7 +115,8 @@ public:
|
||||
sscl::SyncCancelerForAsyncWork &getSyncCanceler()
|
||||
{ return slot.syncCanceler; }
|
||||
|
||||
void setOnSettledHook(std::function<void()> hook)
|
||||
void setOnSettledHook(
|
||||
std::function<void(std::exception_ptr &exceptionPtr)> hook)
|
||||
{
|
||||
if (slot.leaseStatus != SlotLeaseStatus::RESERVED)
|
||||
{
|
||||
@@ -214,7 +214,7 @@ public:
|
||||
std::exception_ptr exceptionPtr = nullptr;
|
||||
sscl::SyncCancelerForAsyncWork syncCanceler;
|
||||
std::unique_ptr<detail::MemberInvokerBase> memberInvoker;
|
||||
std::function<void()> onSettledHook;
|
||||
std::function<void(std::exception_ptr &exceptionPtr)> onSettledHook;
|
||||
};
|
||||
|
||||
void openAdmission()
|
||||
@@ -411,6 +411,8 @@ private:
|
||||
void retireSlot(Slot &slot)
|
||||
{
|
||||
std::function<void()> waiterToInvoke;
|
||||
std::function<void(std::exception_ptr &exceptionPtr)> onSettledHook;
|
||||
std::exception_ptr settledExceptionPtr;
|
||||
|
||||
{
|
||||
sscl::SpinLock::Guard guard(s.lock);
|
||||
@@ -430,33 +432,23 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (slot.onSettledHook) { slot.onSettledHook(); }
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
std::cerr
|
||||
<< "NonViralTaskNursery: onSettled hook exception: "
|
||||
<< e.what() << std::endl;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr
|
||||
<< "NonViralTaskNursery: onSettled hook unknown exception"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if (slot.exceptionPtr) {
|
||||
settledExceptionPtr = slot.exceptionPtr;
|
||||
if (settledExceptionPtr) {
|
||||
slot.settlementStatus = SlotSettlementStatus::EXCEPTION_THROWN;
|
||||
} else {
|
||||
slot.settlementStatus = SlotSettlementStatus::COMPLETED;
|
||||
}
|
||||
|
||||
onSettledHook = std::move(slot.onSettledHook);
|
||||
slot.leaseStatus = SlotLeaseStatus::RETIRED;
|
||||
slot.memberInvoker.reset();
|
||||
waiterToInvoke = takeDrainWaiterIfDrainedUnlocked();
|
||||
}
|
||||
|
||||
if (onSettledHook) {
|
||||
onSettledHook(settledExceptionPtr);
|
||||
}
|
||||
|
||||
if (waiterToInvoke) { waiterToInvoke(); }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user