summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2011-10-14 10:08:26 -0700
committerPixel <pixel@nobis-crew.org>2011-10-14 10:15:34 -0700
commitae657c4c8358b66d1ef867b8f90b1eaebaaa71ea (patch)
tree4fea229168e4d44b4716b423c858797327034a0e
parent20124b259c408a3ad4427df5176553298907106c (diff)
Further tweaks to the Task class: now a Task can declare being smart, and say it's okay to get a EAgain exception, if the operation is interruptible.
-rw-r--r--includes/Handle.h5
-rw-r--r--includes/Task.h24
-rw-r--r--src/Task.cc1
3 files changed, 21 insertions, 9 deletions
diff --git a/includes/Handle.h b/includes/Handle.h
index 8275199..3339699 100644
--- a/includes/Handle.h
+++ b/includes/Handle.h
@@ -4,11 +4,6 @@
namespace Balau {
-class EAgain : public GeneralException {
- public:
- EAgain() : GeneralException("Try Again") { }
-};
-
class ENoEnt : public GeneralException {
public:
ENoEnt(const char * name) : GeneralException(String("No such file or directory: `") + name + "'") { }
diff --git a/includes/Task.h b/includes/Task.h
index b106e9c..3d99d26 100644
--- a/includes/Task.h
+++ b/includes/Task.h
@@ -8,13 +8,21 @@
namespace Balau {
+namespace Events { class BaseEvent; };
+
+class EAgain : public GeneralException {
+ public:
+ EAgain(Events::BaseEvent * evt) : GeneralException("Try Again"), m_evt(evt) { }
+ Events::BaseEvent * getEvent() { return m_evt; }
+ private:
+ Events::BaseEvent * m_evt;
+};
+
class TaskMan;
class Task;
namespace Events {
-class BaseEvent;
-
class Callback {
protected:
virtual void gotEvent(BaseEvent *) = 0;
@@ -81,13 +89,15 @@ class Task {
virtual const char * getName() = 0;
Status getStatus() { return m_status; }
static Task * getCurrentTask();
- static void yield(Events::BaseEvent * evt, bool interruptible = false) {
+ static void yield(Events::BaseEvent * evt, bool interruptible = false) throw (GeneralException) {
Task * t = getCurrentTask();
t->waitFor(evt, true);
do {
t->yield(true);
- } while (!interruptible && !evt->gotSignal());
+ } while ((!interruptible || !t->m_okayToEAgain) && !evt->gotSignal());
+ if (interruptible && t->m_okayToEAgain && !evt->gotSignal())
+ throw EAgain(evt);
}
TaskMan * getTaskMan() { return m_taskMan; }
struct ev_loop * getLoop();
@@ -96,6 +106,11 @@ class Task {
virtual void Do() = 0;
void waitFor(Events::BaseEvent * event, bool override = false);
bool setPreemptible(bool enable);
+ bool setOkayToEAgain(bool enable) {
+ bool oldValue = m_okayToEAgain;
+ m_okayToEAgain = enable;
+ return oldValue;
+ }
private:
size_t stackSize() { return 128 * 1024; }
void switchTo();
@@ -110,6 +125,7 @@ class Task {
typedef std::vector<Events::TaskEvent *> waitedByList_t;
waitedByList_t m_waitedBy;
struct ev_loop * m_loop;
+ bool m_okayToEAgain;
};
};
diff --git a/src/Task.cc b/src/Task.cc
index f7645e6..d31f4e0 100644
--- a/src/Task.cc
+++ b/src/Task.cc
@@ -22,6 +22,7 @@ Balau::Task::Task() {
m_status = STARTING;
m_loop = NULL;
+ m_okayToEAgain = false;
}
Balau::Task::~Task() {