From 9d614195cff948d69df417add0b08b2fe44d4ec5 Mon Sep 17 00:00:00 2001 From: Nicolas Noble Date: Thu, 1 Aug 2013 16:02:21 -0700 Subject: I'm surprised this worked so far. The yield / EAgain mechanism was pretty much broken when using stackless operations. --- includes/Task.h | 10 ++++++---- src/Task.cc | 11 ++++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/includes/Task.h b/includes/Task.h index 3e1b9cf..27cb0bc 100644 --- a/includes/Task.h +++ b/includes/Task.h @@ -167,10 +167,11 @@ class Task { struct ev_loop * getLoop(); bool isStackless() { return m_stackless; } protected: - void yield(bool stillRunning = false) throw (GeneralException); - void yield(Events::BaseEvent * evt) { - waitFor(evt); - yield(); + void yield(Events::BaseEvent * evt = NULL) throw (GeneralException) { + if (evt) + waitFor(evt); + if (yield(false)) + throw EAgain(NULL); } virtual void Do() = 0; void waitFor(Events::BaseEvent * event); @@ -190,6 +191,7 @@ class Task { m_okayToEAgain = true; } private: + bool yield(bool stillRunning); static size_t stackSize() { return 64 * 1024; } void setup(TaskMan * taskMan, void * stack); static bool needsStacks(); diff --git a/src/Task.cc b/src/Task.cc index 8e479c3..77217a5 100644 --- a/src/Task.cc +++ b/src/Task.cc @@ -144,14 +144,14 @@ void Balau::Task::switchTo() { IAssert(m_status != RUNNING, "Task %s at %p is still running... ?", getName(), this); } -void Balau::Task::yield(bool stillRunning) throw (GeneralException) { +bool Balau::Task::yield(bool stillRunning) { Printer::elog(E_TASK, "Task %p - %s yielding", this, getName()); if (stillRunning) m_status = YIELDED; else m_status = SLEEPING; if (m_stackless) { - throw EAgain(NULL); + return true; } else { #ifndef _WIN32 coro_transfer(&m_ctx, &m_taskMan->m_returnContext); @@ -159,6 +159,7 @@ void Balau::Task::yield(bool stillRunning) throw (GeneralException) { SwitchToFiber(m_taskMan->m_fiber); #endif } + return false; } Balau::Task * Balau::Task::getCurrentTask() { @@ -280,10 +281,10 @@ void Balau::Task::operationYield(Events::BaseEvent * evt, enum OperationYieldTyp AAssert(t->m_okayToEAgain, "You can't run a stackless operation from a non-okay-to-eagain task."); } - bool gotSignal; + bool gotSignal, doEAgain = false; do { - t->yield(evt == NULL); + doEAgain = t->yield(evt == NULL); static const char * YieldTypeToString[] = { "SIMPLE", "INTERRUPTIBLE", @@ -296,7 +297,7 @@ void Balau::Task::operationYield(Events::BaseEvent * evt, enum OperationYieldTyp if (!evt) return; - if ((yieldType != SIMPLE) && t->m_okayToEAgain && !gotSignal) { + if ((yieldType != SIMPLE) && t->m_okayToEAgain && !gotSignal && doEAgain) { Printer::elog(E_TASK, "operation is throwing an exception."); throw EAgain(evt); } -- cgit v1.2.3