From: Ralf Jung Date: Mon, 23 Sep 2013 06:37:39 +0000 (+0200) Subject: add a ThreadFunction class and use it X-Git-Url: https://git.ralfj.de/saartuer.git/commitdiff_plain/a89547dadb2928083b7bd859f99cca9c8c61f74b?ds=inline add a ThreadFunction class and use it --- diff --git a/libtuer.py b/libtuer.py index a655fcd..0df4051 100644 --- a/libtuer.py +++ b/libtuer.py @@ -19,3 +19,33 @@ logger = Logger() def log (what): logger.log(what) + +# Threaded callback class +class ThreadFunction(): + _CALL = 0 + _TERM = 1 + + def __init__(self, f): + self._f = f + self._q = queue.Queue() + self._t = threading.Thread(target=self._thread_func) + self._t.start() + + def _thread_func(self): + while True: + (cmd, data) = self._q.get() + # run command + if cmd == _CALL: + self._f(*data) + elif cmd == _TERM: + assert data is None + break + else: + raise NotImplementedError("Command %d does not exist" % cmd) + + def __call__(self, *arg): + self._q.put((self._CALL, arg)) + + def stop(self): + self._q.put((_TERM, None)) + self._t.join() diff --git a/ringd b/ringd index 201322f..b6a27f9 100755 --- a/ringd +++ b/ringd @@ -1,7 +1,7 @@ #!/usr/bin/python3 import time, socket, atexit import queue, threading, select -from libtuer import log +from libtuer import log, ThreadFunction import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) atexit.register(GPIO.cleanup) @@ -9,6 +9,7 @@ atexit.register(GPIO.cleanup) tuerSock = "/run/tuer.sock" ringPin = 18 + # Main classes class PinWatcher(): def __init__(self, pin, histlen): @@ -21,17 +22,8 @@ class PinWatcher(): self._newstate = None # != None iff we are currently seeing a state change self._newstatelen = 0 # only valid if newstate != None # start state change handler thread - self._q = queue.Queue() - self._t = threading.Thread(target=self.queue_consumer) - self._t.start() - - def queue_consumer(self): - while True: - el = self._q.get() - if el is None: return # we are supposed to terminate - # handle the state change - (oldstate, newstate) = el - self.callback(oldstate, newstate) + self._callback = ThreadFunction(self.callback) + self.stop = self._callback.stop def read(self): curstate = GPIO.input(self._pin) @@ -42,7 +34,7 @@ class PinWatcher(): # we already saw this new state self._newstatelen += 1 if self._newstatelen >= self._histlen: - self._q.put((self._state, curstate)) # send stuff to the other thread + self._callback(self._state, curstate) # send stuff to the other thread self._state = curstate self._newstate = None else: @@ -52,10 +44,6 @@ class PinWatcher(): else: # old state is preserved self._newstate = None - - def quit(self): - self._q.put(None) - self._t.join() class RingWatcher(PinWatcher): def __init__(self): @@ -96,4 +84,4 @@ try: time.sleep(0.02) except KeyboardInterrupt: for pin in pins: - pin.quit() + pin.stop()