From 9acc959121735cc72cd68268892af7c277e3e8f2 Mon Sep 17 00:00:00 2001 From: Sean Robinson Date: Sat, 12 Apr 2014 08:48:57 -0700 Subject: [PATCH] Make Dispatcher event loop thread more robust This includes only allowing one such loop at a time and optionally creating a Dispatcher without automatically starting the event loop. The updated tests better reflect the way Dispatcher works now and has worked since commit 5fd979f12f9dd5c4. Signed-off-by: Sean Robinson --- test/unit/pubsub.py | 9 +-------- wifiradar/pubsub.py | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/test/unit/pubsub.py b/test/unit/pubsub.py index 8a5d576..f05641d 100644 --- a/test/unit/pubsub.py +++ b/test/unit/pubsub.py @@ -31,7 +31,7 @@ class TestLimitedDispatcher(unittest.TestCase): """ The Dispatcher tested here does not process messages. """ def setUp(self): - self.dispatch = pubsub.Dispatcher() + self.dispatch = pubsub.Dispatcher(auto_start=False) def test_subscribe(self): """ Test subscribe method. """ @@ -63,7 +63,6 @@ class TestLimitedDispatcher(unittest.TestCase): class TestDispatcher(unittest.TestCase): def setUp(self): self.dispatch = pubsub.Dispatcher() - self.dispatch.start() def test_simple_msg(self): """ Test sending and receiving a message. """ @@ -126,16 +125,12 @@ class TestDispatcher(unittest.TestCase): def tearDown(self): self.dispatch.close() - self.dispatch.join() class TestConnectors(unittest.TestCase): def setUp(self): self.local_dispatch = pubsub.Dispatcher() - self.local_dispatch.start() - self.foreign_dispatch = pubsub.Dispatcher() - self.foreign_dispatch.start() def test_connector(self): """ Test sending through a chain of Dispatchers. """ @@ -194,5 +189,3 @@ class TestConnectors(unittest.TestCase): def tearDown(self): self.local_dispatch.close() self.foreign_dispatch.close() - self.local_dispatch.join() - self.foreign_dispatch.join() diff --git a/wifiradar/pubsub.py b/wifiradar/pubsub.py index 6365960..7219f64 100644 --- a/wifiradar/pubsub.py +++ b/wifiradar/pubsub.py @@ -59,15 +59,17 @@ class Dispatcher(object): publish/subscribe pattern. One Dispatcher should run in each process. """ - def __init__(self): + def __init__(self, auto_start=True): """ Create an empty Dispatcher. """ self.pipes = dict() self._pairs = dict() + self._thread = None self._pipes_lock = RLock() self._watching = Event() self._watching.set() - self.start() + if auto_start: + self.start() def __del__(self): """ Close all pipes when the Dispatcher object is garbage @@ -172,11 +174,15 @@ class Dispatcher(object): def start(self): """ Start running the Dispatcher's event loop in a thread. """ - self._thread = threading.Thread(None, self._run, - 'dispatcher_event_loop:{NAME}'.format(NAME=self), ()) - self._thread.start() + # Only allow one event loop thread. + if self._thread is None: + self._thread = threading.Thread(None, self._run, + 'dispatcher_event_loop:{NAME}'.format(NAME=self), ()) + self._thread.start() def join(self): """ Stop the Dispatcher's event loop thread. """ - self._thread.join() + if self._thread is not None: + self._thread.join() + self._thread = None -- 2.11.4.GIT