summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2011-11-17 11:17:57 -0800
committerPixel <pixel@nobis-crew.org>2011-11-17 11:17:57 -0800
commit2cb2961c9f6062e867b6ccc3d9067f55c7b81ea4 (patch)
tree7846e0849a6f2cde216596a1ab144a69c50f5a60
parente435e4bb3c0744acf5b36c6e441d309d10af1257 (diff)
Cleaning some code, redesigning a bit the stack allocation problem from the task manager, and actually implementing it properly.
-rw-r--r--includes/Task.h6
-rw-r--r--includes/TaskMan.h4
-rw-r--r--includes/Threads.h2
-rw-r--r--src/Task.cc6
-rw-r--r--src/TaskMan.cc32
5 files changed, 39 insertions, 11 deletions
diff --git a/includes/Task.h b/includes/Task.h
index 5865831..2e52747 100644
--- a/includes/Task.h
+++ b/includes/Task.h
@@ -5,7 +5,7 @@
#include <coro.h>
#endif
#include <ev++.h>
-#include <vector>
+#include <list>
#include <Exceptions.h>
#include <Printer.h>
@@ -136,7 +136,7 @@ class Task {
TaskMan * getMyTaskMan() { return m_taskMan; }
private:
static size_t stackSize() { return 64 * 1024; }
- void setup(TaskMan * taskMan);
+ void setup(TaskMan * taskMan, void * stack);
static bool needsStacks();
void switchTo();
static void CALLBACK coroutineTrampoline(void *);
@@ -152,7 +152,7 @@ class Task {
void * m_tls;
friend class TaskMan;
friend class Events::TaskEvent;
- typedef std::vector<Events::TaskEvent *> waitedByList_t;
+ typedef std::list<Events::TaskEvent *> waitedByList_t;
waitedByList_t m_waitedBy;
bool m_okayToEAgain;
};
diff --git a/includes/TaskMan.h b/includes/TaskMan.h
index b944f09..c63695a 100644
--- a/includes/TaskMan.h
+++ b/includes/TaskMan.h
@@ -6,7 +6,7 @@
#endif
#include <ev++.h>
#include <ext/hash_set>
-#include <vector>
+#include <queue>
#include <Threads.h>
#include <Exceptions.h>
@@ -55,6 +55,8 @@ class TaskMan {
struct ev_loop * m_loop;
bool m_allowedToSignal;
ev::async m_evt;
+ std::queue<void *> m_stacks;
+ int m_nStacks;
};
template<class T>
diff --git a/includes/Threads.h b/includes/Threads.h
index a1f270e..256e8e3 100644
--- a/includes/Threads.h
+++ b/includes/Threads.h
@@ -41,7 +41,7 @@ template<class T>
class Queue {
public:
Queue() { pthread_cond_init(&m_cond, NULL); }
- ~Queue() { pthread_cond_destroy(&m_cond); }
+ ~Queue() { while (size()) pop(); pthread_cond_destroy(&m_cond); }
void push(T & t) {
m_lock.enter();
m_queue.push(t);
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;