Hi Jason and everyone else, attached a patch how I think a BackgroundTask should look like. I added BackgroundTask to async.py and use it in Process and Thread. Tell me what you think.
On a site-notice: We have Thread() that has a start() function. This class calls a function in a new thread. This class is a BackgroundTask. On the other side we have ThreadCallback which has a register function to schedule the task in a thread with a given name. This object is an InProgress object. This is confusing. First of all ThreadCallback should be a BackgroundTask _having_ an InProgress object. I also think 'register' should be called 'schedule' or even better, try to merge Thread and ThreadCallback. And why do we call MainThreadCallback using __call__? OK, we do the same for Callback, but MainThreadCallback takes some time. Maybe the function should be called start, too. Comments please Dischi
Index: src/notifier/thread.py =================================================================== --- src/notifier/thread.py (revision 2969) +++ src/notifier/thread.py (working copy) @@ -60,7 +60,7 @@ # notifier imports import nf_wrapper as notifier from callback import Callback, Signal -from async import InProgress +from async import InProgress, BackgroundTask # get logging object log = logging.getLogger('notifier') @@ -127,7 +127,7 @@ return None -class Thread(threading.Thread): +class Thread(threading.Thread, BackgroundTask): """ Notifier aware wrapper for threads. When a thread is started, it is impossible to fork the current process into a second one without exec both @@ -135,16 +135,12 @@ """ def __init__(self, function, *args, **kargs): threading.Thread.__init__(self) + BackgroundTask.__init__(self) self.function = function self.args = args self.kargs = kargs - self.signals = { - "completed": Signal(), - "exception": Signal() - } - def wait_on_exit(self, wait=False): """ Wait for the thread on application exit. Default is True. @@ -162,15 +158,12 @@ self.join() + @BackgroundTask.startBackgroundTask() def start(self): """ Start the thread and return an InProgress object. """ - r = InProgress() - self.signals['completed'].connect_once(r.finished) - self.signals['exception'].connect_once(r.exception) super(Thread, self).start() - return r def run(self): Index: src/notifier/async.py =================================================================== --- src/notifier/async.py (revision 2969) +++ src/notifier/async.py (working copy) @@ -29,7 +29,7 @@ # # ----------------------------------------------------------------------------- -__all__ = [ 'InProgress' ] +__all__ = [ 'InProgress', 'BackgroundTask' ] # python imports import logging @@ -200,3 +200,32 @@ will be emited only once. """ return Signal._connect(self, callback, args, kwargs, True, weak, pos) + + +class BackgroundTask(object): + """ + Task running in the background. This objects provides a 'completed' and + an 'exception' signal and a decorator to create an InProgress object. + """ + def __init__(self): + self.signals = { + 'completed': Signal(), + 'exception': Signal() + } + + def startBackgroundTask(): + def decorator(func): + def newfunc(*args, **kwargs): + async = InProgress() + self.signals['completed'].connect_once(async.finished) + self.signals['exception'].connect_once(async.exception) + func(*args, **kwargs) + return async + try: + newfunc.func_name = func.func_name + except TypeError: + pass + return newfunc + return decorator + + startBackgroundTask = staticmethod(startBackgroundTask) Index: src/notifier/popen.py =================================================================== --- src/notifier/popen.py (revision 2969) +++ src/notifier/popen.py (working copy) @@ -58,14 +58,14 @@ import nf_wrapper as notifier from callback import Signal, Callback from thread import MainThreadCallback, is_mainthread -from async import InProgress +from async import InProgress, BackgroundTask # get logging object log = logging.getLogger('notifier') # FIXME: rewrite :) -class Process(object): +class Process(BackgroundTask): """ Base class for started child processes """ @@ -75,14 +75,11 @@ of arguments (similar to popen2). If debugname is given, the stdout and stderr will also be written. """ - + BackgroundTask.__init__(self) # Setup signal handlers for the process; allows the class to be # useful without subclassing. - self.signals = { - "stderr": Signal(), - "stdout": Signal(), - "completed": Signal(), - } + self.signals['stderr'] = Signal() + self.signals['stdout'] = Signal() self._cmd = self._normalize_cmd(cmd) self._stop_cmd = None @@ -91,7 +88,6 @@ self.stopping = False self.__kill_timer = None self.child = None - self.in_progress = None def _normalize_cmd(self, cmd): @@ -134,6 +130,7 @@ return cmdlist + @BackgroundTask.startBackgroundTask() def start(self, args = None): """ Starts the process. If args is not None, it can be either a list or @@ -166,8 +163,6 @@ MainThreadCallback(proclist.append, self, self.__child_died ) else: proclist.append( self, self.__child_died ) - self.in_progress = InProgress() - return self.in_progress def get_pid(self): @@ -330,8 +325,6 @@ self.child = None if self.__kill_timer: notifier.timer_remove( self.__kill_timer ) - self.in_progress.finished(status >> 8) - self.in_progress = None self.signals['completed'].emit(status >> 8)
-- If the facts don't fit the theory, change the facts. -- Albert Einstein
pgp72RPj5JLiV.pgp
Description: PGP signature
------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________ Freevo-devel mailing list Freevo-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/freevo-devel