[kupfer: 11/27] task: Redesign task API to be start with finish callback
- From: Ulrik Sverdrup <usverdrup src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [kupfer: 11/27] task: Redesign task API to be start with finish callback
- Date: Tue, 16 Feb 2010 20:48:02 +0000 (UTC)
commit e5630ace9b7b538b94bd94ded108cab18b985d8d
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date: Tue Feb 9 15:52:50 2010 +0100
task: Redesign task API to be start with finish callback
kupfer/task.py | 121 ++++++++++++++++++++-----------------------------------
1 files changed, 44 insertions(+), 77 deletions(-)
---
diff --git a/kupfer/task.py b/kupfer/task.py
index 7b48577..ae15a8a 100644
--- a/kupfer/task.py
+++ b/kupfer/task.py
@@ -1,3 +1,4 @@
+import sys
import threading
import gobject
@@ -6,51 +7,20 @@ from kupfer import scheduler, pretty
class Task (object):
"""Represent a task that can be done in the background"""
- def __init__(self):
- self.name = None
+ def __init__(self, name=None):
+ self.name = name
def __unicode__(self):
return self.name
- def is_thread(self):
- return False
-
- def run(self):
+ def start(self, finish_callback):
raise NotImplementedError
-class StepTask (Task):
- """A step task runs a part of the task in StepTask.step,
- doing final cleanup in StepTask.finish, which is guaranteed to
- be called regardless of exit or failure mode
- """
- def step(self):
- """Do a small part of the task.
- Return True to continue processing,
- or a False value to finish.
- """
- pass
- def finish(self):
- pass
- def run(self):
- try:
- while True:
- if not self.step():
- break
- yield
- finally:
- self.finish()
-
class ThreadTask (Task):
"""Run in a thread"""
- def __init__(self):
- Task.__init__(self)
-
- def is_thread(self):
- return True
-
- def _run_thread(self):
- self.thread_do()
- gobject.idle_add(self.thread_finish)
+ def __init__(self, name=None):
+ Task.__init__(self, name)
+ self.finish_callback = None
def thread_do(self):
"""Override this to run what should be done in the thread"""
@@ -62,59 +32,56 @@ class ThreadTask (Task):
"""
pass
- def run(self):
- thread = None
- while True:
- if not thread:
- thread = threading.Thread(target=self._run_thread)
- thread.start()
- elif not thread.isAlive():
- return
- yield
+ def thread_finally(self, exc_info):
+ """Always run at thread finish"""
+ pass
+
+ def _thread_finally(self, exc_info):
+ try:
+ self.thread_finally(exc_info)
+ finally:
+ self.finish_callback(self)
+
+ def _run_thread(self):
+ try:
+ self.thread_do()
+ gobject.idle_add(self.thread_finish)
+ except:
+ exc_info = sys.exc_info()
+ raise
+ else:
+ exc_info = None
+ finally:
+ gobject.idle_add(self._thread_finally, exc_info)
+
+ def start(self, finish_callback):
+ self.finish_callback = finish_callback
+ thread = threading.Thread(target=self._run_thread)
+ thread.start()
+
class TaskRunner (pretty.OutputMixin):
"""Run Tasks in the idle Loop"""
def __init__(self, end_on_finish):
- self.task_iters = {}
- self.thread_iters = {}
- self.idle_timer = scheduler.Timer(True)
+ self.tasks = set()
self.end_on_finish = end_on_finish
scheduler.GetScheduler().connect("finish", self._finish_cleanup)
+ def _task_finished(self, task):
+ self.output_debug("Task finished", task)
+ self.tasks.remove(task)
+
def add_task(self, task):
"""Register @task to be run"""
- if task.is_thread():
- # start thread
- self.thread_iters[task] = task.run()
- # run through all threads
- self._step_tasks(self.thread_iters)
- else:
- self.task_iters[task] = task.run()
- self._setup_timers()
-
- def _setup_timers(self):
- if self.task_iters:
- self.idle_timer.set_idle(self._step_tasks, self.task_iters)
-
- def _step_tasks(self, tasks):
- for task, task_iter in tasks.items():
- try:
- task_iter.next()
- except StopIteration:
- self.output_debug("Task done:", task)
- del tasks[task]
- self._setup_timers()
+ self.tasks.add(task)
+ task.start(self._task_finished)
def _finish_cleanup(self, sched):
if self.end_on_finish:
- self.task_iters.clear()
- self.thread_iters.clear()
+ self.tasks.clear()
return
- self._step_tasks(self.thread_iters)
- if self.task_iters or self.thread_iters:
+ if self.tasks:
self.output_info("Uncompleted tasks:")
- for task in self.task_iters:
- self.output_info(task)
- for task in self.thread_iters:
+ for task in self.tasks:
self.output_info(task)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]