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

Attachment: 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

Reply via email to