summaryrefslogtreecommitdiff
path: root/viengoos/activity.c
diff options
context:
space:
mode:
authorneal <neal>2008-02-13 15:00:48 +0000
committerneal <neal>2008-02-13 15:00:48 +0000
commit131af073d55b7e2d3409337610d0fb469a059bd1 (patch)
treeba6dbb80327c0836181bbfc1b155ca6f8013fc61 /viengoos/activity.c
parent5f0f3e50ed8c0c9e1164371180ffd92a9bb35b0a (diff)
2008-02-13 Neal H. Walfield <neal@gnu.org>
* activity.h (activity_policy_update): New declaration. * activity.c (children_list_insert_after): New function. (children_list_detach): Likewise. (activity_prepare): Use the above to insert ACTIVITY onto its parent's children list. Keep the list is priority sorted order. (activity_deprepare): Likewise, but to remove ACTIVITY from its parent's children list. (activity_policy_update): New function. * server.c (server_loop): Use activity_policy_update to update an activity's policy.
Diffstat (limited to 'viengoos/activity.c')
-rw-r--r--viengoos/activity.c121
1 files changed, 110 insertions, 11 deletions
diff --git a/viengoos/activity.c b/viengoos/activity.c
index 3c2267c..8013af5 100644
--- a/viengoos/activity.c
+++ b/viengoos/activity.c
@@ -27,6 +27,50 @@
struct activity *root_activity;
+/* Add ACTIVITY to ACTIVITY->PARENT's children list after AFTER. */
+static void
+children_list_insert_after (struct activity *activity, struct activity *after)
+{
+ assert (activity->parent);
+
+ if (! after)
+ /* Insert at head of list. */
+ {
+ activity->sibling_next = activity->parent->children;
+ if (activity->parent->children)
+ activity->parent->children->sibling_prev = activity;
+ activity->parent->children = activity;
+ }
+ else
+ {
+ assert (activity->parent == after->parent);
+ assert (after->policy.sibling_rel.priority
+ >= activity->policy.sibling_rel.priority);
+
+ activity->sibling_next = after->sibling_next;
+ activity->sibling_prev = after;
+ if (activity->sibling_next)
+ activity->sibling_next->sibling_prev = activity;
+ after->sibling_next = activity;
+ }
+}
+
+/* Remove ACTIVITY from ACTIVITY->PARENT's children list. */
+static void
+children_list_detach (struct activity *activity)
+{
+ if (activity->sibling_prev)
+ activity->sibling_prev->sibling_next = activity->sibling_next;
+ else
+ {
+ assert (activity->parent->children == activity);
+ activity->parent->children = activity->sibling_next;
+ }
+
+ if (activity->sibling_next)
+ activity->sibling_next->sibling_prev = activity->sibling_prev;
+}
+
void
activity_create (struct activity *parent,
struct activity *child)
@@ -284,12 +328,26 @@ activity_prepare (struct activity *principal, struct activity *activity)
assert (! activity->parent->children
|| ! activity->parent->children->sibling_prev);
- activity->sibling_next = activity->parent->children;
- if (activity->parent->children)
- activity->parent->children->sibling_prev = activity;
- activity->parent->children = activity;
+ if (! activity->parent->children
+ || (activity->policy.sibling_rel.priority
+ >= activity->parent->children->policy.sibling_rel.priority))
+ children_list_insert_after (activity, NULL);
+ else
+ {
+ struct activity *last;
+
+ for (last = activity->parent->children;
+ last->sibling_next
+ && (last->sibling_next->policy.sibling_rel.priority
+ > activity->policy.sibling_rel.priority);
+ last = last->sibling_next)
+ ;
+
+ assert (last);
+ children_list_insert_after (activity, last);
+ }
- /* We have no in-memory children. */
+ /* ACTIVITY has no in-memory children. */
activity->children = NULL;
}
@@ -308,16 +366,57 @@ activity_deprepare (struct activity *principal, struct activity *victim)
/* Unlink from parent's children list. */
assert (victim->parent);
- if (victim->sibling_prev)
- victim->sibling_prev->sibling_next = victim->sibling_next;
+ children_list_detach (victim);
+}
+
+void
+activity_policy_update (struct activity *activity,
+ struct activity_policy policy)
+{
+ int priority = policy.sibling_rel.priority;
+
+ if (priority == activity->policy.sibling_rel.priority)
+ /* Same priority: noop. */
+ ;
+ else if (priority > activity->policy.sibling_rel.priority)
+ /* Increased priority. Search backwards and find the first
+ activity that has a priority that is greater than or equal to
+ PRIORITY. Move ACTIVITY to just after that activity. */
+ {
+ activity->policy.sibling_rel.priority = priority;
+
+ struct activity *prev;
+ for (prev = activity->sibling_prev;
+ prev && prev->policy.sibling_rel.priority < priority;
+ prev = prev->sibling_prev)
+ ;
+
+ if (prev != activity->sibling_prev)
+ {
+ children_list_detach (activity);
+ children_list_insert_after (activity, prev);
+ }
+ }
else
+ /* Decreased priority. */
{
- assert (victim->parent->children == victim);
- victim->parent->children = victim->sibling_next;
+ activity->policy.sibling_rel.priority = priority;
+
+ struct activity *next;
+ for (next = activity;
+ next->sibling_next
+ && next->sibling_next->policy.sibling_rel.priority > priority;
+ next = next->sibling_next)
+ ;
+
+ if (next != activity)
+ {
+ children_list_detach (activity);
+ children_list_insert_after (activity, next);
+ }
}
- if (victim->sibling_next)
- victim->sibling_next->sibling_prev = victim->sibling_prev;
+ activity->policy = policy;
}
static void