# HG changeset patch # User Thinker K.F. Li # Date 1294711454 -28800 # Node ID 2f9fa5d59e6715771895cfa5e12bc3b38accbbfb # Parent 45e9566ea5c00d1581bcb17d7672ebb22bf1590f Add data_monitor meta-class to monitor accessing on domview_ui. - The monitoring is to prevent from reentry triggered by DOM events. - call 'do*' methods of a monitored class would try to lock domview_ui at first. - The method would not be executed actually if being fault to lock. - You can make monitor to print debug message with environment variable - DATA_MONITOR_DBG=1, or - DATA_MONITOR_DBG=2 diff -r 45e9566ea5c0 -r 2f9fa5d59e67 pyink/MBScene.py --- a/pyink/MBScene.py Mon Jan 10 22:15:16 2011 +0800 +++ b/pyink/MBScene.py Tue Jan 11 10:04:14 2011 +0800 @@ -37,12 +37,68 @@ # scene into two scenes with the same content. # +## \brief Monitor accessing on the dta model. +# +# This class is a meta-class that monitor data accessing for its instance +# classes. +# +# All methods, of instance classes, who's name is prefixed with 'do' are +# monitored. When a monitored method was called, monitor will try to lock +# _domview of the object. The method is only called if successfully acquiring +# the lock, or return immediately. The lock is released after the calling +# returned. +# +class data_monitor(type): + def __new__(mclazz, name, bases, clazz_dict): + import os + + debug_level = 0 + if os.environ.has_key('DATA_MONITOR_DBG'): + debug_level = int(os.environ['DATA_MONITOR_DBG']) + pass + + def gen_sentinel(name, func): + def sentinel(self, *args, **kws): + if debug_level >= 1: + print 'calling %s' % (name) + pass + if debug_level >= 2: + print ' args: %s' % (repr(args)) + print ' kws: %s' % (repr(kws)) + pass + + if not self._domview.lock(): # can not lock + return + + try: + func(self, *args, **kws) + finally: + self._domview.unlock() + pass + pass + return sentinel + + for attr_name in clazz_dict: + if (not attr_name.startswith('do')) or \ + (not callable(clazz_dict[attr_name])): + continue + clazz_dict[attr_name] = \ + gen_sentinel(attr_name, clazz_dict[attr_name]) + pass + + clazz = type.__new__(mclazz, name, bases, clazz_dict) + + return clazz + pass + ## \brief MBScene connect GUI and DOM-tree # # This method accepts user actions and involves domview_ui to update # data on the document. # class MBScene(object): + __metaclass__ = data_monitor + _tween_type_names = ('normal', 'scale') _num_frames_of_line = 100 diff -r 45e9566ea5c0 -r 2f9fa5d59e67 pyink/domview_ui.py --- a/pyink/domview_ui.py Mon Jan 10 22:15:16 2011 +0800 +++ b/pyink/domview_ui.py Tue Jan 11 10:04:14 2011 +0800 @@ -639,5 +639,11 @@ @property def root(self): return self._root + + def lock(self): + return True + + def unlock(self): + return True pass