Ejemplo n.º 1
0
 def __init__(self, **kwargs):
     kwargs['ParentEmissionThread'] = None
     self.IsParentEmissionThread = kwargs.get('IsParentEmissionThread', False)
     thread_id = setID(kwargs.get('thread_id'))
     if thread_id in _THREADS:
         newid = '__'.join([thread_id, setID(None)])
         self.LOG.warning('thread_id %s already exists using %s' % (thread_id, newid))
         thread_id = newid
     _THREADS[thread_id] = self
     self.AllowedEmissionThreads = set()
     self.AllowedEmissionThreads |= set(kwargs.get('AllowedEmissionThreads', []))
     self.AllowedEmissionThreads.add(thread_id)
     threading.Thread.__init__(self, name=thread_id)
     OSCBaseObject.__init__(self, **kwargs)
     self._thread_id = thread_id
     self._insertion_lock = Lock()
     self.Events = {}
     timed_events = []
     
     for cls in iterbases(self, 'OSCBaseObject'):
         if not hasattr(cls, '_Events'):
             continue
         for key in cls._Events.iterkeys():
             e = self.Properties[key]
             self.Events[key] = e
             if e.wait_timeout is not None:
                 timed_events.append(e.name)
     self._threaded_calls_idle = True
     timed_events.reverse()
     self.timed_events = timed_events
     self._threaded_calls_queue = collections.deque()
     self._timed_calls_queue = TimeQueue()
     self.disable_threaded_call_waits = kwargs.get('disable_threaded_call_waits', False)
Ejemplo n.º 2
0
    def __init__(self, **kwargs):
        kwargs['ParentEmissionThread'] = None
        self.IsParentEmissionThread = kwargs.get('IsParentEmissionThread',
                                                 False)
        thread_id = setID(kwargs.get('thread_id'))
        if thread_id in _THREADS:
            newid = '__'.join([thread_id, setID(None)])
            self.LOG.warning('thread_id %s already exists using %s' %
                             (thread_id, newid))
            thread_id = newid
        _THREADS[thread_id] = self
        self.AllowedEmissionThreads = set()
        self.AllowedEmissionThreads |= set(
            kwargs.get('AllowedEmissionThreads', []))
        self.AllowedEmissionThreads.add(thread_id)
        threading.Thread.__init__(self, name=thread_id)
        OSCBaseObject.__init__(self, **kwargs)
        self._thread_id = thread_id
        self._insertion_lock = Lock()
        self.Events = {}
        timed_events = []

        for cls in iterbases(self, 'OSCBaseObject'):
            if not hasattr(cls, '_Events'):
                continue
            for key in cls._Events.iterkeys():
                e = self.Properties[key]
                self.Events[key] = e
                if e.wait_timeout is not None:
                    timed_events.append(e.name)
        self._threaded_calls_idle = True
        timed_events.reverse()
        self.timed_events = timed_events
        self._threaded_calls_queue = collections.deque()
        self._timed_calls_queue = TimeQueue()
        self.disable_threaded_call_waits = kwargs.get(
            'disable_threaded_call_waits', False)
Ejemplo n.º 3
0
class BaseThread(OSCBaseObject, threading.Thread):
    _Events = {'_running':{}, 
               '_stopped':{}, 
               '_threaded_call_ready':dict(wait_timeout=.1), 
               '_threaded_calls_idle':{}}
    _Properties = {'_thread_id':dict(default='')}
    def __new__(*args, **kwargs):
        events_by_cls = {}
        props_by_cls = {}
        cls = args[0]
        if cls != BaseThread:
            while issubclass(cls, BaseThread):
                d = {}
                p = {}
                events = cls.__dict__.get('_Events')
                if events is None:
                    cls = cls.__bases__[0]
                    continue
                props = cls.__dict__.get('_Properties', {})
                for key, val in events.iteritems():
                    e_kwargs = val.copy()
                    e_kwargs.setdefault('default', False)
                    additional_kwargs = e_kwargs.get('additional_property_kwargs', {})
                    additional_kwargs['wait_timeout'] = e_kwargs.get('wait_timeout')
                    e_kwargs['additional_property_kwargs'] = additional_kwargs
                    e_kwargs['ObjPropertyClass'] = Event
                    props[key] = e_kwargs
                setattr(cls, '_Properties', props)
                cls = cls.__bases__[0]
        return OSCBaseObject.__new__(*args, **kwargs)
    def __init__(self, **kwargs):
        kwargs['ParentEmissionThread'] = None
        self.IsParentEmissionThread = kwargs.get('IsParentEmissionThread', False)
        thread_id = setID(kwargs.get('thread_id'))
        if thread_id in _THREADS:
            newid = '__'.join([thread_id, setID(None)])
            self.LOG.warning('thread_id %s already exists using %s' % (thread_id, newid))
            thread_id = newid
        _THREADS[thread_id] = self
        self.AllowedEmissionThreads = set()
        self.AllowedEmissionThreads |= set(kwargs.get('AllowedEmissionThreads', []))
        self.AllowedEmissionThreads.add(thread_id)
        threading.Thread.__init__(self, name=thread_id)
        OSCBaseObject.__init__(self, **kwargs)
        self._thread_id = thread_id
        self._insertion_lock = Lock()
        self.Events = {}
        timed_events = []
        
        for cls in iterbases(self, 'OSCBaseObject'):
            if not hasattr(cls, '_Events'):
                continue
            for key in cls._Events.iterkeys():
                e = self.Properties[key]
                self.Events[key] = e
                if e.wait_timeout is not None:
                    timed_events.append(e.name)
        self._threaded_calls_idle = True
        timed_events.reverse()
        self.timed_events = timed_events
        self._threaded_calls_queue = collections.deque()
        self._timed_calls_queue = TimeQueue()
        self.disable_threaded_call_waits = kwargs.get('disable_threaded_call_waits', False)
        
    @property
    def pethread_log(self):
        return pethread_logger
        
    @property
    def can_currentthread_emit(self):
        name = threading.currentThread().name
        val = name in self.AllowedEmissionThreads
        #print 'Thread %s can emit=%s currentthread=%s' % (self.name, val, name)
        return val
        
    def get_now_for_timed_calls(self):
        return time.time()
        
    def insert_threaded_call(self, call, *args, **kwargs):
        p = None
        if self.can_currentthread_emit:
            call(*args, **kwargs)
            return
        with self._insertion_lock:
            if self.IsParentEmissionThread:
                self.pethread_log('insert call', call, ' to PEThread %s' % (self.name))
            kwargs = kwargs.copy()
            kwargs['__PartialObjOwnerThread__'] = self
            p = WeakPartial(call, self._on_WeakPartial_dead, *args, **kwargs)
            if p.call_time is not None:
                self._timed_calls_queue.put(p.call_time, p)
            else:
                self._threaded_calls_queue.append(p)
            self._threaded_calls_idle = False
            self._cancel_event_timeouts()
        return p
        
    def _on_WeakPartial_dead(self, p):
        callqueue = self._threaded_calls_queue
        timequeue = self._timed_calls_queue
        print '%s WeakPartial %s dead' % (self._thread_id, p)
        with self._insertion_lock:
            if p in callqueue:
                callqueue.remove(p)
                print '%s removed %s from callqueue' % (self._thread_id, p)
            if p.call_time is not None and p.call_time in timequeue.times:
                r = timequeue.remove(time=p.call_time, item=p)
                print '%s removed %s from timequeue, result=%s' % (self._thread_id, p, r)
        
    def _cancel_event_timeouts(self, events=None):
        if events is None:
            events = self.timed_events
        for key in events:
            e = self.Events.get(key)
            if not e:
                continue
            e.set()
            
    def run(self):
        disable_call_waits = self.disable_threaded_call_waits
        do_threaded_calls = self._do_threaded_calls
        do_timed_calls = self._do_timed_calls
        loop_iteration = self._thread_loop_iteration
        self._running = True
        while self._running:
            if True:#self._running:
                loop_iteration()
                if not disable_call_waits:
                    self._threaded_call_ready.wait()
                    do_threaded_calls()
                    do_timed_calls()
        self._stopped = True
        
    def stop(self, **kwargs):
        blocking = kwargs.get('blocking', False)
        wait_for_queues = kwargs.get('wait_for_queues', True)
        self._running = False
        if self._thread_id in _THREADS:
            del _THREADS[self._thread_id]
        if wait_for_queues:
            if not len(self._threaded_calls_queue):
                self._threaded_call_ready = True
            self._cancel_event_timeouts()
        else:
            self._threaded_calls_queue.clear()
            self._threaded_call_ready = True
        if not self.isAlive():
            self._stopped = True
        if blocking and threading.currentThread() != self:
            if type(blocking) in [float, int]:
                timeout = float(blocking)
            else:
                timeout = None
            self._stopped.wait(timeout)
        
    def _thread_loop_iteration(self):
        pass
        
    def _do_threaded_calls(self):
        queue = self._threaded_calls_queue
        with self._insertion_lock:
            if not len(queue):
                if self._running:
                    if not len(self._timed_calls_queue):
                        self._threaded_call_ready = False
                        self._threaded_calls_idle = True
                return
            p = queue.popleft()
        if p.is_dead:
            print 'PARTIAL %s already dead' % (p)
        if self.IsParentEmissionThread:
            self.pethread_log('do_call: ', repr(p))
        try:
            #result = p()
            result = self._really_do_call(p)
            return (result, p.cb, p.args, p.kwargs)
        except:
            self.LOG.warning(traceback.format_exc())
    def _do_timed_calls(self):
        queue = self._timed_calls_queue
        with self._insertion_lock:
            lowest_time = queue.lowest_time()
            now = self.get_now_for_timed_calls()
            if lowest_time is None or now < lowest_time:
                if self._running:
                    if not len(self._threaded_calls_queue):
                        self._threaded_call_ready = False
                        self._threaded_calls_idle = True
                return
            p = queue.pop(lowest_time)
        if self.IsParentEmissionThread:
            self.pethread_log('do_timed_call, now=%s: %r' % (now, p))
        try:
            result = self._really_do_call(p)
            return (result, p.cb, p.args, p.kwargs)
        except:
            self.LOG.warning(traceback.format_exc())
        
    def _really_do_call(self, p):
        return p()
Ejemplo n.º 4
0
class BaseThread(OSCBaseObject, threading.Thread):
    _Events = {
        '_running': {},
        '_stopped': {},
        '_threaded_call_ready': dict(wait_timeout=.1),
        '_threaded_calls_idle': {}
    }
    _Properties = {'_thread_id': dict(default='')}

    def __new__(*args, **kwargs):
        events_by_cls = {}
        props_by_cls = {}
        cls = args[0]
        if cls != BaseThread:
            while issubclass(cls, BaseThread):
                d = {}
                p = {}
                events = cls.__dict__.get('_Events')
                if events is None:
                    cls = cls.__bases__[0]
                    continue
                props = cls.__dict__.get('_Properties', {})
                for key, val in events.iteritems():
                    e_kwargs = val.copy()
                    e_kwargs.setdefault('default', False)
                    additional_kwargs = e_kwargs.get(
                        'additional_property_kwargs', {})
                    additional_kwargs['wait_timeout'] = e_kwargs.get(
                        'wait_timeout')
                    e_kwargs['additional_property_kwargs'] = additional_kwargs
                    e_kwargs['ObjPropertyClass'] = Event
                    props[key] = e_kwargs
                setattr(cls, '_Properties', props)
                cls = cls.__bases__[0]
        return OSCBaseObject.__new__(*args, **kwargs)

    def __init__(self, **kwargs):
        kwargs['ParentEmissionThread'] = None
        self.IsParentEmissionThread = kwargs.get('IsParentEmissionThread',
                                                 False)
        thread_id = setID(kwargs.get('thread_id'))
        if thread_id in _THREADS:
            newid = '__'.join([thread_id, setID(None)])
            self.LOG.warning('thread_id %s already exists using %s' %
                             (thread_id, newid))
            thread_id = newid
        _THREADS[thread_id] = self
        self.AllowedEmissionThreads = set()
        self.AllowedEmissionThreads |= set(
            kwargs.get('AllowedEmissionThreads', []))
        self.AllowedEmissionThreads.add(thread_id)
        threading.Thread.__init__(self, name=thread_id)
        OSCBaseObject.__init__(self, **kwargs)
        self._thread_id = thread_id
        self._insertion_lock = Lock()
        self.Events = {}
        timed_events = []

        for cls in iterbases(self, 'OSCBaseObject'):
            if not hasattr(cls, '_Events'):
                continue
            for key in cls._Events.iterkeys():
                e = self.Properties[key]
                self.Events[key] = e
                if e.wait_timeout is not None:
                    timed_events.append(e.name)
        self._threaded_calls_idle = True
        timed_events.reverse()
        self.timed_events = timed_events
        self._threaded_calls_queue = collections.deque()
        self._timed_calls_queue = TimeQueue()
        self.disable_threaded_call_waits = kwargs.get(
            'disable_threaded_call_waits', False)

    @property
    def pethread_log(self):
        return pethread_logger

    @property
    def can_currentthread_emit(self):
        name = threading.currentThread().name
        val = name in self.AllowedEmissionThreads
        #print 'Thread %s can emit=%s currentthread=%s' % (self.name, val, name)
        return val

    def get_now_for_timed_calls(self):
        return time.time()

    def insert_threaded_call(self, call, *args, **kwargs):
        p = None
        if self.can_currentthread_emit:
            call(*args, **kwargs)
            return
        with self._insertion_lock:
            if self.IsParentEmissionThread:
                self.pethread_log('insert call', call,
                                  ' to PEThread %s' % (self.name))
            kwargs = kwargs.copy()
            kwargs['__PartialObjOwnerThread__'] = self
            p = WeakPartial(call, self._on_WeakPartial_dead, *args, **kwargs)
            if p.call_time is not None:
                self._timed_calls_queue.put(p.call_time, p)
            else:
                self._threaded_calls_queue.append(p)
            self._threaded_calls_idle = False
            self._cancel_event_timeouts()
        return p

    def _on_WeakPartial_dead(self, p):
        callqueue = self._threaded_calls_queue
        timequeue = self._timed_calls_queue
        print '%s WeakPartial %s dead' % (self._thread_id, p)
        with self._insertion_lock:
            if p in callqueue:
                callqueue.remove(p)
                print '%s removed %s from callqueue' % (self._thread_id, p)
            if p.call_time is not None and p.call_time in timequeue.times:
                r = timequeue.remove(time=p.call_time, item=p)
                print '%s removed %s from timequeue, result=%s' % (
                    self._thread_id, p, r)

    def _cancel_event_timeouts(self, events=None):
        if events is None:
            events = self.timed_events
        for key in events:
            e = self.Events.get(key)
            if not e:
                continue
            e.set()

    def run(self):
        disable_call_waits = self.disable_threaded_call_waits
        do_threaded_calls = self._do_threaded_calls
        do_timed_calls = self._do_timed_calls
        loop_iteration = self._thread_loop_iteration
        self._running = True
        while self._running:
            if True:  #self._running:
                loop_iteration()
                if not disable_call_waits:
                    self._threaded_call_ready.wait()
                    do_threaded_calls()
                    do_timed_calls()
        self._stopped = True

    def stop(self, **kwargs):
        blocking = kwargs.get('blocking', False)
        wait_for_queues = kwargs.get('wait_for_queues', True)
        self._running = False
        if self._thread_id in _THREADS:
            del _THREADS[self._thread_id]
        if wait_for_queues:
            if not len(self._threaded_calls_queue):
                self._threaded_call_ready = True
            self._cancel_event_timeouts()
        else:
            self._threaded_calls_queue.clear()
            self._threaded_call_ready = True
        if not self.isAlive():
            self._stopped = True
        if blocking and threading.currentThread() != self:
            if type(blocking) in [float, int]:
                timeout = float(blocking)
            else:
                timeout = None
            self._stopped.wait(timeout)

    def _thread_loop_iteration(self):
        pass

    def _do_threaded_calls(self):
        queue = self._threaded_calls_queue
        with self._insertion_lock:
            if not len(queue):
                if self._running:
                    if not len(self._timed_calls_queue):
                        self._threaded_call_ready = False
                        self._threaded_calls_idle = True
                return
            p = queue.popleft()
        if p.is_dead:
            print 'PARTIAL %s already dead' % (p)
        if self.IsParentEmissionThread:
            self.pethread_log('do_call: ', repr(p))
        try:
            #result = p()
            result = self._really_do_call(p)
            return (result, p.cb, p.args, p.kwargs)
        except:
            self.LOG.warning(traceback.format_exc())

    def _do_timed_calls(self):
        queue = self._timed_calls_queue
        with self._insertion_lock:
            lowest_time = queue.lowest_time()
            now = self.get_now_for_timed_calls()
            if lowest_time is None or now < lowest_time:
                if self._running:
                    if not len(self._threaded_calls_queue):
                        self._threaded_call_ready = False
                        self._threaded_calls_idle = True
                return
            p = queue.pop(lowest_time)
        if self.IsParentEmissionThread:
            self.pethread_log('do_timed_call, now=%s: %r' % (now, p))
        try:
            result = self._really_do_call(p)
            return (result, p.cb, p.args, p.kwargs)
        except:
            self.LOG.warning(traceback.format_exc())

    def _really_do_call(self, p):
        return p()