add a ThreadFunction class and use it
authorRalf Jung <post@ralfj.de>
Mon, 23 Sep 2013 06:37:39 +0000 (08:37 +0200)
committerRalf Jung <post@ralfj.de>
Mon, 23 Sep 2013 06:37:39 +0000 (08:37 +0200)
libtuer.py
ringd

index a655fcd2858f275c937ed2444f40737082451fa9..0df4051203cf8cad29da53d439dd263e39449922 100644 (file)
@@ -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 201322f4f640ff80f46d594e1946578e5b08ec12..b6a27f940ea9fe5ebccd23a77ba07e439bfce699 100755 (executable)
--- 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()