diff --git a/src/base/coroutine.hh b/src/base/coroutine.hh index d28889296e..35c3ab9433 100644 --- a/src/base/coroutine.hh +++ b/src/base/coroutine.hh @@ -161,14 +161,21 @@ class Coroutine : public Fiber * it needs to run. The first argument of the function should be a * reference to the Coroutine::caller_type which the * routine will use as a way for yielding to the caller. + * The optional second boolean argument controls if the Coroutine + * should be run on creation, which mimics Boost's Coroutine + * semantics by default. This can be disabled as an optimization to + * avoid unnecessary context switches on Coroutine creation. * * @param f task run by the coroutine + * @param run_coroutine set to false to disable running the coroutine + * immediately after it is created */ - Coroutine(std::function f) + Coroutine(std::function f, bool run_coroutine = true) : Fiber(), task(f), caller(*this) { - // Create and Run the Coroutine - this->call(); + // When desired, run the Coroutine after it is created + if (run_coroutine) + this->call(); } virtual ~Coroutine() {} diff --git a/src/base/coroutine.test.cc b/src/base/coroutine.test.cc index 655bc254a5..586686972e 100644 --- a/src/base/coroutine.test.cc +++ b/src/base/coroutine.test.cc @@ -43,6 +43,25 @@ using namespace m5; +/** + * This test is checking if the Coroutine, once it's created + * it doesn't start since the second argument of the constructor + * (run_coroutine) is set to false + */ +TEST(Coroutine, Unstarted) +{ + auto yielding_task = + [] (Coroutine::CallerType& yield) + { + yield(); + }; + + const bool start_upon_creation = false; + Coroutine coro(yielding_task, start_upon_creation); + + ASSERT_FALSE(coro.started()); +} + /** * This test is checking if the Coroutine, once it yields * back to the caller, it is still marked as not finished.