threads.py
1 """Threading primitives for the network package""" 2 3 import logging 4 import random 5 import threading 6 from contextlib import contextmanager 7 8 9 class StoppableThread(threading.Thread): 10 """Base class for application threads with stopThread method""" 11 name = None 12 logger = logging.getLogger('default') 13 14 def __init__(self, name=None): 15 if name: 16 self.name = name 17 super(StoppableThread, self).__init__(name=self.name) 18 self.stop = threading.Event() 19 self._stopped = False 20 random.seed() 21 self.logger.info('Init thread %s', self.name) 22 23 def stopThread(self): 24 """Stop the thread""" 25 self._stopped = True 26 self.stop.set() 27 28 29 class BusyError(threading.ThreadError): 30 """ 31 Thread error raised when another connection holds the lock 32 we are trying to acquire. 33 """ 34 pass 35 36 37 @contextmanager 38 def nonBlocking(lock): 39 """ 40 A context manager which acquires given lock non-blocking 41 and raises BusyError if failed to acquire. 42 """ 43 locked = lock.acquire(False) 44 if not locked: 45 raise BusyError 46 try: 47 yield 48 finally: 49 lock.release()