From 49a147e7f402e50c536ea751c53a500d3c6ecda6 Mon Sep 17 00:00:00 2001 From: Vadim Skipin Date: Wed, 6 May 2026 20:24:30 +0000 Subject: [PATCH] Call parameters dtor for non trivial types --- include/silk/fibers/fiber.h | 17 +++++++++++++++-- src/fibers/fiber.cpp | 19 ++++++++++++++----- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/include/silk/fibers/fiber.h b/include/silk/fibers/fiber.h index 79fc76f..fed7b0a 100644 --- a/include/silk/fibers/fiber.h +++ b/include/silk/fibers/fiber.h @@ -27,6 +27,12 @@ static constexpr uint64_t FIBER_PARAMETERS_SIZE = 64; */ using FiberMain = int(void * parameters) noexcept; +/** + * Destructor for the fiber's parameter buffer. Called after the entry point returns. + * Null for trivially destructible parameter types. + */ +using ParametersDtor = void(void * parameters) noexcept; + /** * Cooperative fiber scheduler with per-CPU threads, async IO, and work-stealing. */ @@ -57,7 +63,8 @@ class FiberScheduler [[nodiscard]] static int run(int (*fiberMain)(T *) noexcept, T && parameters, FiberFuture * future) noexcept { static_assert(sizeof(T) <= FIBER_PARAMETERS_SIZE); - Fiber * fiber = allocateFiber(reinterpret_cast(fiberMain), future); + Fiber * fiber = allocateFiber( + reinterpret_cast(fiberMain), std::is_trivially_destructible_v ? nullptr : destroyParameters, future); if (fiber) { std::construct_at(static_cast(getFiberParameters(fiber)), std::forward(parameters)); @@ -355,9 +362,15 @@ class FiberScheduler // Helpers. // + template + static void destroyParameters(void * p) noexcept + { + std::destroy_at(static_cast(p)); + } + static void buildStealCandidates() noexcept; static void * getFiberParameters(Fiber * fiber) noexcept; - static Fiber * allocateFiber(FiberMain * fiberMain, FiberFuture * future) noexcept; + static Fiber * allocateFiber(FiberMain * fiberMain, ParametersDtor * parametersDtor, FiberFuture * future) noexcept; static void freeFiber(Fiber * fiber) noexcept; static void enqueueReady(Fiber * fiber) noexcept; static void yieldSuspendCallback(Fiber * fiber, void * context) noexcept; diff --git a/src/fibers/fiber.cpp b/src/fibers/fiber.cpp index 6b3f5df..a0f3c6e 100644 --- a/src/fibers/fiber.cpp +++ b/src/fibers/fiber.cpp @@ -117,7 +117,7 @@ class Fiber Fiber(bool isProxyFiber = false) noexcept; ~Fiber() noexcept; - bool initialize(FiberMain * fiberMain, FiberFuture * waitingFuture) noexcept; + bool initialize(FiberMain * fiberMain, ParametersDtor * parametersDtor, FiberFuture * waitingFuture) noexcept; void deinitialize() noexcept; void switchToFiberContext() noexcept; @@ -193,8 +193,11 @@ class Fiber // dummy is stored here so it can be reused. QueueBase::QueueNode queueNode; - // Entry point and parameters buffer. + // Entry point, parameters buffer, and optional parameters destructor. + // parametersDtor is set by run for non-trivially-destructible T and + // called by fiberContextMain immediately after fiberMain returns. FiberMain * fiberMain = nullptr; + ParametersDtor * parametersDtor = nullptr; uint8_t parameters[FIBER_PARAMETERS_SIZE]; #if defined(__SANITIZE_ADDRESS__) @@ -250,7 +253,7 @@ Fiber::~Fiber() noexcept } } -bool Fiber::initialize(FiberMain * fiberMain_, FiberFuture * waitingFuture_) noexcept +bool Fiber::initialize(FiberMain * fiberMain_, ParametersDtor * parametersDtor_, FiberFuture * waitingFuture_) noexcept { state.store(FiberState::SUSPENDED, std::memory_order_relaxed); @@ -289,6 +292,7 @@ bool Fiber::initialize(FiberMain * fiberMain_, FiberFuture * waitingFuture_) noe #endif fiberMain = fiberMain_; + parametersDtor = parametersDtor_; fiberContext = boost::context::detail::make_fcontext( static_cast(stack) + PAGE_SIZE + FIBER_STACK_SIZE, FIBER_STACK_SIZE, fiberContextMain); @@ -299,6 +303,11 @@ void Fiber::deinitialize() noexcept { ASSERT(!suspendedEntry.is_linked()); + if (parametersDtor) + { + parametersDtor(parameters); + } + #if defined(__SANITIZE_THREAD__) TSAN_FIBER_DESTROY(tsanFiber); tsanFiber = nullptr; @@ -1034,12 +1043,12 @@ void * FiberScheduler::getFiberParameters(Fiber * fiber) noexcept return fiber->parameters; } -Fiber * FiberScheduler::allocateFiber(FiberMain * fiberMain, FiberFuture * future) noexcept +Fiber * FiberScheduler::allocateFiber(FiberMain * fiberMain, ParametersDtor * parametersDtor, FiberFuture * future) noexcept { Fiber * fiber = scheduler->fiberPool.allocate(); if (fiber) { - if (fiber->initialize(fiberMain, future)) + if (fiber->initialize(fiberMain, parametersDtor, future)) { Perf::getSimpleCounter(simpleCounters[FIBER_STARTED]).increment(); return fiber;