Author: dmeyer
Date: Sun Feb  5 14:52:46 2006
New Revision: 1164

Added:
   trunk/base/src/notifier/decorators.py
   trunk/base/test/decorator.py
Modified:
   trunk/base/src/notifier/__init__.py

Log:
Add some decorators to avoid duplicate code all this time. In many
cases Timer or used to simulate stepping or delayed callbacks. And
the execute_in_thread and execute_in_mainloop decorators will make
sure a function is called in the correct thread context.


Modified: trunk/base/src/notifier/__init__.py
==============================================================================
--- trunk/base/src/notifier/__init__.py (original)
+++ trunk/base/src/notifier/__init__.py Sun Feb  5 14:52:46 2006
@@ -47,6 +47,8 @@
 from jobserver import killall as kill_jobserver
 from kaa.base import utils
 
+from decorators import execute_in_timer, execute_in_thread, execute_in_mainloop
+
 # get logging object
 log = logging.getLogger('notifier')
 

Added: trunk/base/src/notifier/decorators.py
==============================================================================
--- (empty file)
+++ trunk/base/src/notifier/decorators.py       Sun Feb  5 14:52:46 2006
@@ -0,0 +1,138 @@
+# -*- coding: iso-8859-1 -*-
+# -----------------------------------------------------------------------------
+# decorators.py - Some helping decorators based on kaa.notifier
+# -----------------------------------------------------------------------------
+# $Id$
+#
+# -----------------------------------------------------------------------------
+# kaa-notifier - Notifier Wrapper
+# Copyright (C) 2005 Dirk Meyer, et al.
+#
+# First Version: Dirk Meyer <[EMAIL PROTECTED]>
+# Maintainer:    Dirk Meyer <[EMAIL PROTECTED]>
+#
+# Please see the file AUTHORS for a complete list of authors.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MER-
+# CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# -----------------------------------------------------------------------------
+
+__all__ = [ 'execute_in_timer', 'execute_in_thread', 'execute_in_mainloop' ]
+
+# notifier thread imports
+from thread import MainThreadCallback, is_mainthread
+from jobserver import ThreadCallback
+
+def execute_in_timer(timer, interval, type=''):
+    """
+    Decorator to call the decorated function in a Timer. When calling the
+    function, a timer will be started with the given interval calling that
+    function. This decorater is usefull for putting a huge task into smaller
+    once calling each task in one step of the main loop or execute a function
+    delayed. The parameter timer is the timer class to use (Timer or WeakTimer
+    for stepping or OneShotTimer or WeakOneShotTimer for delayed). The 
parameter
+    type can be used to force having only one timer active at one time. Set
+    type to 'once' to make sure only the first active timer is executed, a
+    later one will be ignored or 'override' to remove the current timer and
+    activate the new call. If you use 'once' or 'override', keep in mind that
+    if you call the function with different parameters only one call gets
+    executed.
+    """
+
+    if not type in ('', 'once', 'override'):
+        raise RunTimeError('invalid type %s' % type)
+
+    def decorator(func):
+
+        def newfunc(*args, **kwargs):
+            if not type:
+                # just start the timer
+                timer(func, *args, **kwargs).start(interval)
+                return True
+
+            # Try to find out if the function is bound to an object.
+            # FIXME: maybe this is bad solution, how fast is comparing
+            # the func_code attributes?
+            obj = func
+            if args and args[0] and hasattr(args[0], func.func_name) and \
+                   newfunc.func_code == getattr(args[0], 
func.func_name).func_code:
+                obj = args[0]
+            # check current timer
+            if hasattr(obj, '__kaa_timer_decorator') and \
+                   obj.__kaa_timer_decorator.active():
+                if type == 'once':
+                    # timer already running and not override
+                    return False
+                # stop old timer
+                obj.__kaa_timer_decorator.stop()
+
+            # create new timer, set it to the object and start it
+            obj.__kaa_timer_decorator = timer(func, *args, **kwargs)
+            obj.__kaa_timer_decorator.start(interval)
+            return True
+        try:
+            newfunc.func_name = func.func_name
+        except TypeError:
+            pass
+        return newfunc
+
+    return decorator
+
+
+def execute_in_mainloop(async=False):
+    """
+    This decorator makes sure the function is called from the main loop. If
+    the calling thread is the mainloop, it is a normal function call, if not,
+    MainThreadCallback is used to call the function. If 'async' is set to 
False,
+    the thread will wait for the answer. It is possible with this decorator to
+    have a longer codeblock in a thread and call functions not thread save.
+    """
+    def decorator(func):
+
+        def newfunc(*args, **kwargs):
+            if is_mainthread():
+                return func(*args, **kwargs)
+            t = MainThreadCallback(func, *args, **kwargs)
+            t.set_async(async)
+            return t()
+
+        try:
+            newfunc.func_name = func.func_name
+        except TypeError:
+            pass
+        return newfunc
+
+    return decorator
+
+
+def execute_in_thread(name):
+    """
+    The decorator makes sure the function is always called in the thread
+    with the given name. There is no way to get the results of the call,
+    make sure you define a callback n the function attributes are you need
+    to use ThreadCallback without this decorator.
+    """
+    def decorator(func):
+
+        def newfunc(*args, **kwargs):
+            ThreadCallback(func, *args, **kwargs).register(name)
+
+        try:
+            newfunc.func_name = func.func_name
+        except TypeError:
+            pass
+        return newfunc
+
+    return decorator

Added: trunk/base/test/decorator.py
==============================================================================
--- (empty file)
+++ trunk/base/test/decorator.py        Sun Feb  5 14:52:46 2006
@@ -0,0 +1,48 @@
+from kaa.notifier import execute_in_timer, Timer, OneShotTimer, loop, \
+     is_mainthread, execute_in_thread, execute_in_mainloop
+
+
+class Foo(object):
+
+    @execute_in_timer(Timer, 0.1, 'once')
+    def poll(self, x):
+        if not x:
+            return False
+        y = x.pop(0)
+        print y
+        return True
+
+    @execute_in_thread('name')
+    def foo(self):
+        print 'foo is mainthread:', is_mainthread()
+        self.bar()
+        
+    @execute_in_mainloop()
+    def bar(self):
+        print 'bar is mainthread:', is_mainthread()
+        
+
[EMAIL PROTECTED](Timer, 0.1, 'override')
+def poll(x):
+    if not x:
+        return False
+    y = x.pop(0)
+    print y
+    return True
+
+
[EMAIL PROTECTED](OneShotTimer, 0.1)
+def bla(f, msg):
+    print msg
+    f.foo()
+    f.bar()
+    
+f = Foo()
+f.poll([0,1,2,3,4,5])
+
+poll([10,11,12,13,14,15])
+bla(f, 'test')
+bla(f, 'test2')
+OneShotTimer(poll, [20,21,22,23,24]).start(0.3)
+OneShotTimer(f.poll, [30,31,32,33,34]).start(0.3)
+loop()


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to