mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-29 06:32:40 -06:00
130 lines
4 KiB
Python
Executable file
130 lines
4 KiB
Python
Executable file
"""
|
|
This test gives an example of how some computation results from an
|
|
auxiliary thread could be 'published' via pubsub in a thread-safe
|
|
manner, in a 'gui'-like application, ie an application where the
|
|
main thread is in an infinite event loop and supports the callback
|
|
of user-defined functions when the gui is idle.
|
|
|
|
The worker thread 'work' is to increment a counter
|
|
as fast as interpreter can handle. Every so often (every resultStep counts),
|
|
the thread stores the count in a synchronized queue, for later retrieval
|
|
by the main thread. In parallel to this, the main thread loops forever (or
|
|
until user interrupts via keyboard), doing some hypothetical work
|
|
(represented by the sleep(1) call) and calling all registered 'idle'
|
|
callbacks. The transfer is done by extracting items from the queue and
|
|
publishing them via pubsub.
|
|
|
|
Oliver Schoenborn
|
|
May 2009
|
|
|
|
:copyright: Copyright 2008-2009 by Oliver Schoenborn, all rights reserved.
|
|
:license: BSD, see LICENSE.txt for details.
|
|
|
|
"""
|
|
|
|
|
|
__author__="schoenb"
|
|
__date__ ="$31-May-2009 9:11:41 PM$"
|
|
|
|
from Queue import Queue
|
|
import time
|
|
import threading
|
|
|
|
from pubsub import pub
|
|
from pubsub.py2and3 import print_
|
|
|
|
|
|
resultStep = 1000000 # how many counts for thread "result" to be available
|
|
|
|
|
|
def threadObserver(transfers, threadObj, count):
|
|
"""Listener that listens for data from testTopic. This function
|
|
doesn't know where the data comes from (or in what thread it was
|
|
generated... but threadObj is the thread in which this
|
|
threadObserver is called and should indicate Main thread)."""
|
|
|
|
print_(transfers, threadObj, count / resultStep)
|
|
|
|
pub.subscribe(threadObserver, 'testTopic')
|
|
|
|
|
|
def onIdle():
|
|
"""This should be registered with 'gui' to be called when gui is idle
|
|
so we get a chance to transfer data from aux thread without blocking
|
|
the gui. Ie this function must spend as little time as possible so
|
|
'gui' remains reponsive."""
|
|
thread.transferData()
|
|
|
|
|
|
class ParaFunction(threading.Thread):
|
|
"""
|
|
Represent a function running in a parallel thread. The thread
|
|
just increments a counter and puts the counter value on a synchronized
|
|
queue every resultStep counts. The content of the queue can be published by
|
|
calling transferData().
|
|
"""
|
|
|
|
def __init__(self):
|
|
threading.Thread.__init__(self)
|
|
self.running = False # set to True when thread should stop
|
|
self.count = 0 # our workload: keep counting!
|
|
self.queue = Queue() # to transfer data to main thread
|
|
self.transfer = 0 # count how many transfers occurred
|
|
|
|
def run(self):
|
|
print_('aux thread started')
|
|
self.running = True
|
|
while self.running:
|
|
self.count += 1
|
|
if self.count % resultStep == 0:
|
|
self.queue.put(self.count)
|
|
|
|
print_('aux thread done')
|
|
|
|
def stop(self):
|
|
self.running = False
|
|
|
|
def transferData(self):
|
|
"""Send data from aux thread to main thread. The data was put in
|
|
self.queue by the aux thread, and this queue is a Queue.Queue which
|
|
is a synchronized queue for inter-thread communication.
|
|
Note: This method must be called from main thread."""
|
|
self.transfer += 1
|
|
while not self.queue.empty():
|
|
pub.sendMessage('testTopic',
|
|
transfers = self.transfer,
|
|
threadObj = threading.currentThread(),
|
|
count = self.queue.get())
|
|
|
|
|
|
thread = ParaFunction()
|
|
|
|
|
|
def main():
|
|
idleFns = [] # list of functions to call when 'gui' idle
|
|
idleFns.append( onIdle )
|
|
|
|
try:
|
|
thread.start()
|
|
|
|
print_('starting event loop')
|
|
eventLoop = True
|
|
while eventLoop:
|
|
time.sleep(1) # pretend that main thread does other stuff
|
|
for idleFn in idleFns:
|
|
idleFn()
|
|
|
|
except KeyboardInterrupt:
|
|
print_('Main interrupted, stopping aux thread')
|
|
thread.stop()
|
|
|
|
except Exception as exc:
|
|
from pubsub import py2and3
|
|
exc = py2and3.getexcobj()
|
|
print_(exc)
|
|
print_('Exception, stopping aux thread')
|
|
thread.stop()
|
|
|
|
|
|
main()
|
|
|