Jason Tackaberry wrote:
> On 2008-01-17 14:06, Dirk Meyer wrote:
>> Yes, conceptually they are the same, but the implentation is a very
>> different. 'main' needs a completly different JobServer. Right now we
>> have MainThreadCallback is a simple class, we would have to greate a
>> MainJobServer to inherit MainThreadCallback from JobServer. This is
>> writing code without the API feeling different.
>>   
>
> It might well be the case that although they are similar in concept in
> implementation they are so different that trying to reuse code will just
> complicate things.  I'm not too familiar with how jobserver works so I'd
> have to look at it.

Please do. Attached a patch that handles ThreadCallback similar to
Thread and Process but adds a __call__ method.

> I find in_progress more readable actually, and more easily distinguished
> from class names.  But regardless, I'm going to oppose changing our
> naming conventions now because this is a far, far more massive and
> intrusive change than anything we've done so far (it affects almost
> every other line of every kaa module) and the reason is only cosmetic.

OK, it was just a test :)


Index: test/asynctest.py
===================================================================
--- test/asynctest.py	(revision 2969)
+++ test/asynctest.py	(working copy)
@@ -202,6 +202,10 @@
     time.sleep(0.1)
     kaa.notifier.step()
     kaa.notifier.shutdown()
-    
+
+def dummy():
+    pass
+
+kaa.notifier.Timer(dummy).start(1)
 foo().connect(end)
 kaa.notifier.loop()
Index: src/notifier/jobserver.py
===================================================================
--- src/notifier/jobserver.py	(revision 2969)
+++ src/notifier/jobserver.py	(working copy)
@@ -6,7 +6,7 @@
 #
 # -----------------------------------------------------------------------------
 # kaa.notifier - Mainloop and callbacks
-# Copyright (C) 2005, 2006 Dirk Meyer, Jason Tackaberry, et al.
+# Copyright (C) 2005-2008 Dirk Meyer, Jason Tackaberry, et al.
 #
 # First Version: Dirk Meyer <[EMAIL PROTECTED]>
 # Maintainer:    Dirk Meyer <[EMAIL PROTECTED]>
@@ -39,7 +39,7 @@
 
 # kaa notifier imports
 from callback import Signal, Callback
-from async import InProgress
+from async import InProgress, BackgroundTask
 from thread import MainThreadCallback
 import thread
 
@@ -75,12 +75,10 @@
     return decorator
 
 
-class ThreadCallback(InProgress):
+class ThreadCallback(BackgroundTask):
     """
     A callback to run a function in a thread. This class is used by
     execute_in_thread, but it is also possible to use this call directly.
-    The class inherits from InProgress and will call the connected functions
-    on termination or exception.
     """
     def __init__(self, function, *args, **kwargs):
         super(ThreadCallback, self).__init__()
@@ -95,19 +93,37 @@
         return self._server != None
 
 
-    def register(self, name, priority=0):
+    def set_thread(self, name, priority=0):
         """
-        Register callback to a thread with the given name.
+        Set thread this callback should be executed it.
         """
-        if self._server:
-            return
         self.priority = priority
         if not _threads.has_key(name):
             _threads[name] = _Thread(name)
         self._server = _threads[name]
+
+
+    @BackgroundTask.start_background_task()
+    def __call__(self):
+        """
+        Execute the thread. set_thread _must_ before calling the
+        function or __call__ will crash.
+        """
+        if not self._server:
+            raise RuntimeError('ThreadCallback not connected to a thread')
         self._server.add(self)
 
+        
+    def register(self, name=None, priority=0):
+        """
+        Register callback to a thread with the given name.
+        """
+        if self._server:
+            raise RuntimeError()
+        self.set_thread(name, priority)
+        return self()
 
+
     def stop(self):
         """
         Remove the callback from the thread schedule if still active.
@@ -181,10 +197,10 @@
             # process the job
             job._server = None
             try:
-                MainThreadCallback(job.finished, job._callback())()
+                MainThreadCallback(job.signals['completed'].emit, job._callback())()
             except Exception, e:
                 e._exc_info = sys.exc_info()
-                MainThreadCallback(job.exception, e)()
+                MainThreadCallback(job.signals['exception'].emit, e)()
         # server stopped
         log.debug('stop thread %s' % self.name)
 
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.start_background_task()
     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 start_background_task():
+        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
+    
+    start_background_task = staticmethod(start_background_task)
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.start_background_task()
     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)
 
 
-- 
A computer scientist is someone who, when told to 'Go to Hell', sees
the 'go to', rather than the destination, as harmful.

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