diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Task.cc | 6 | ||||
| -rw-r--r-- | src/TaskMan.cc | 32 | 
2 files changed, 32 insertions, 6 deletions
| diff --git a/src/Task.cc b/src/Task.cc index d72decc..440ed0e 100644 --- a/src/Task.cc +++ b/src/Task.cc @@ -21,12 +21,14 @@ bool Balau::Task::needsStacks() {  #endif  } -void Balau::Task::setup(TaskMan * taskMan) { +void Balau::Task::setup(TaskMan * taskMan, void * stack) {      size_t size = stackSize();  #ifndef _WIN32 -    m_stack = taskMan->getStack(); +    Assert(stack); +    m_stack = stack;      coro_create(&m_ctx, coroutineTrampoline, this, m_stack, size);  #else +    Assert(!stack);      m_stack = NULL;      m_fiber = CreateFiber(size, coroutineTrampoline, this);  #endif diff --git a/src/TaskMan.cc b/src/TaskMan.cc index e9e3485..3a5cc1c 100644 --- a/src/TaskMan.cc +++ b/src/TaskMan.cc @@ -19,6 +19,8 @@ const char * Stopper::getName() {  static Balau::DefaultTmpl<Balau::TaskMan> defaultTaskMan(50);  static Balau::LocalTmpl<Balau::TaskMan> localTaskMan; +static const int TOO_MANY_STACKS = 1024; +  namespace Balau {  class TaskScheduler : public Thread, public AtStart, public AtExit { @@ -109,6 +111,8 @@ Balau::TaskMan::TaskMan() : m_stopped(false), m_allowedToSignal(false) {      m_evt.set<asyncDummy>();      m_evt.start();      s_scheduler.registerTaskMan(this); + +    m_nStacks = 0;  }  #ifdef _WIN32 @@ -129,21 +133,40 @@ Balau::TaskMan * Balau::TaskMan::getDefaultTaskMan() { return localTaskMan.get()  Balau::TaskMan::~TaskMan() {      Assert(localTaskMan.getGlobal() != this); +    while (m_stacks.size() != 0) { +        free(m_stacks.front()); +        m_stacks.pop(); +    }      s_scheduler.unregisterTaskMan(this);      // probably way more work to do here in order to clean up tasks from that thread      ev_loop_destroy(m_loop);  }  void * Balau::TaskMan::getStack() { -    return malloc(Task::stackSize()); +    void * r = NULL; +    if (m_nStacks == 0) { +        if (Task::needsStacks()) +            r = malloc(Task::stackSize()); +    } else { +        r = m_stacks.front(); +        m_stacks.pop(); +        m_nStacks--; +    } +    return r;  }  void Balau::TaskMan::freeStack(void * stack) { -    free(stack); +    if (!stack) +        return; +    if (m_nStacks >= TOO_MANY_STACKS) { +        free(stack); +    } else { +        m_stacks.push(stack); +        m_nStacks++; +    }  }  void Balau::TaskMan::mainLoop() { -    // We need at least one round before bailing :)      do {          taskHash_t::iterator iH;          Task * t; @@ -200,7 +223,7 @@ void Balau::TaskMan::mainLoop() {          while (((m_pendingAdd.size() != 0) || (m_tasks.size() == 0)) && !m_stopped) {              t = m_pendingAdd.pop();              Assert(m_tasks.find(t) == m_tasks.end()); -            t->setup(this); +            t->setup(this, getStack());              m_tasks.insert(t);          } @@ -212,6 +235,7 @@ void Balau::TaskMan::mainLoop() {                  t = *iH;                  if (((t->getStatus() == Task::STOPPED) || (t->getStatus() == Task::FAULTED)) &&                       (t->m_waitedBy.size() == 0)) { +                    freeStack(t->m_stack);                      delete t;                      m_tasks.erase(iH);                      didDelete = true; | 
