diff --git a/emper/Runtime.cpp b/emper/Runtime.cpp index 31c7b1c232545aeddd141fa6f9348554bf29d6e9..9969fcc03453f7ea3251fd65deda234b6450b507 100644 --- a/emper/Runtime.cpp +++ b/emper/Runtime.cpp @@ -87,15 +87,13 @@ Runtime::Runtime(workerid_t workerCount, RuntimeStrategyFactory& strategyFactory currentRuntime = this; } - // initialize the global and all worker IoContexts - if constexpr (emper::IO) { + // initialize the global IoContext if a completer is used + if constexpr (emper::IO && emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) { // The global io_uring needs at least workerCount entries in its SQ because // for each worker's IoContext one eventfd read is prepared before the // globalCompleter is started and submits all previously prepared sqes. globalIo = new GlobalIoContext(*this, workerCount); - if constexpr (emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) { - globalIo->startGlobalCompleter(); - } + globalIo->startGlobalCompleter(); if constexpr (emper::STATS) { globalIo->stats.workerId = emper::io::Stats::GLOBAL_COMPLETER_ID; @@ -178,10 +176,12 @@ Runtime::~Runtime() { delete[] threads; if constexpr (emper::IO) { - // It is safer to destroy the globalIo before the worker IoContexts - // because pointer to the worker IoContexts can outlife their objects - // in the globalCompleter - delete globalIo; + if constexpr (emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) { + // It is safer to destroy the globalIo before the worker IoContexts + // because pointer to the worker IoContexts can outlife their objects + // in the globalCompleter + delete globalIo; + } for (unsigned int i = 0; i < workerCount; ++i) { delete ioContexts[i]; @@ -286,7 +286,7 @@ void Runtime::initiateTermination() { wakeupSem.notify_many(workerCount); - if constexpr (emper::IO) { + if constexpr (emper::IO && emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) { globalIo->initiateTermination(); } } @@ -299,7 +299,7 @@ void Runtime::waitUntilFinished() { } } - if constexpr (emper::IO) { + if constexpr (emper::IO && emper::IO_COMPLETER_BEHAVIOR != emper::IoCompleterBehavior::none) { globalIo->waitUntilFinished(); } diff --git a/emper/io/Future.hpp b/emper/io/Future.hpp index b9c073232ab28cd091191b031b67cb7b916f06bb..d0978de740cc9c636b812765ef2cb6d3fa76d723 100644 --- a/emper/io/Future.hpp +++ b/emper/io/Future.hpp @@ -18,8 +18,9 @@ #include "BinaryPrivateSemaphore.hpp" // for BPS #include "CallerEnvironment.hpp" // for CallerEnvironment, ANYWHERE #include "Common.hpp" -#include "Debug.hpp" // for LOGD, LogSubsystem, LogSubsyst... -#include "Emper.hpp" // for DEBUG +#include "Debug.hpp" // for LOGD, LogSubsystem, LogSubsyst... +#include "Emper.hpp" // for DEBUG +#include "Runtime.hpp" #include "io/Operation.hpp" // for Operation, operator<<, Operati... struct io_uring_sqe; @@ -387,7 +388,15 @@ class PartialCompletableFuture : public Future { } auto completeAndGetContinuation(int32_t res) -> Fiber* override { - CompletionType completion = tryComplete<CallerEnvironment::ANYWHERE>(res); + CompletionType completion; + + // If there is no completer we must be in a emper worker + // Otherwise decide at runtime where the possible partialCompletion should be resubmitted + if (emper::IO_COMPLETER_BEHAVIOR == emper::IoCompleterBehavior::none || Runtime::inRuntime()) { + completion = tryComplete<CallerEnvironment::EMPER>(res); + } else { + completion = tryComplete<CallerEnvironment::ANYWHERE>(res); + } switch (completion) { case CompletionType::Resubmission: