Skip to content

Commit c616647

Browse files
author
Charles Weir
committed
cw: Got runTillFirstCompletes working for new Coroutine implementation.
1 parent 84555db commit c616647

2 files changed

Lines changed: 37 additions & 17 deletions

File tree

BrickPython/Coroutine.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class StopCoroutineException( Exception ):
1616

1717
class Coroutine( threading.Thread ):
1818
def __init__(self, func, *args, **kwargs):
19+
print "Coroutine: %r %r" % (args, kwargs)
1920
threading.Thread.__init__(self)
2021
self.args = args
2122
self.kwargs = kwargs
@@ -48,17 +49,20 @@ def run(self):
4849
exc_type, exc_value, exc_traceback = sys.exc_info()
4950
trace = "".join(traceback.format_tb(exc_traceback))
5051
self.logger.debug( "Traceback (latest call first):\n %s" % trace )
52+
self.stopEvent.set() # Need to tell caller to do a join.
5153
self.callerSemaphore.release()
5254
threading.Thread.run(self) # Does some cleanup.
5355

5456
def call(self, param = None):
5557
'''Executed from the caller thread. Runs the coroutine until it calls wait.
5658
Does nothing if the thread has terminated.
5759
If a parameter is passed, it is returned from the Coroutine.wait() function in the coroutine thread.'''
58-
if self.isAlive():
60+
if self.is_alive():
5961
self.callParam = param
6062
self.mySemaphore.release()
6163
self.callerSemaphore.acquire()
64+
if self.stopEvent.is_set():
65+
self.join() # Ensure that is_alive is false on exit.
6266
return self.callResult
6367

6468
def stop(self):
@@ -85,12 +89,27 @@ def wait(param = None):
8589

8690
@staticmethod
8791
def waitMilliseconds(timeMillis):
88-
'Called from within the coroutine to wait the given time'
92+
'''Called from within the coroutine to wait the given time.
93+
I.e. Invocations of the coroutine using call() will do nothing until then. '''
8994
startTime = Coroutine.currentTimeMillis()
9095
while Coroutine.currentTimeMillis() - startTime < timeMillis:
9196
Coroutine.wait()
9297

93-
# while not self.stopEvent.is_set():
98+
@staticmethod
99+
def runTillFirstCompletes(*coroutines):
100+
def runTillFirstCompletesFunc(*coroutineList):
101+
while True:
102+
for c in coroutineList:
103+
c.call()
104+
if not c.is_alive():
105+
break
106+
Coroutine.wait()
107+
for c in coroutineList:
108+
if c.is_alive():
109+
c.stop()
110+
111+
result = Coroutine(runTillFirstCompletesFunc, *coroutines)
112+
return result
94113

95114
#
96115
# self.scheduler.coroutines.remove( self )

test/TestCoroutine.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@
1414
import logging
1515
from mock import *
1616

17+
logging.basicConfig(format='%(message)s', level=logging.DEBUG) # Logging is a simple print
18+
1719
class TestCoroutine(unittest.TestCase):
1820
''' Tests for the Scheduler class, its built-in coroutines, and its coroutine handling.
1921
'''
2022
coroutineCalls = []
2123
@staticmethod
22-
def dummyCoroutineFunc():
23-
for i in range(1, 5):
24+
def dummyCoroutineFunc(start=1, end=5):
25+
logging.debug( "in dummyCoroutineFunc %d %d" %(start, end) )
26+
for i in range(start, end):
2427
TestCoroutine.coroutineCalls.append(i)
2528
Coroutine.wait();
2629

@@ -32,7 +35,7 @@ def dummyCoroutineFuncThatDoesCleanup():
3235
Coroutine.wait()
3336
finally:
3437
TestCoroutine.coroutineCalls.append( -1 )
35-
38+
3639
def setUp(self):
3740
TestCoroutine.coroutineCalls = []
3841

@@ -45,7 +48,9 @@ def testCoroutinesGetCalledUntilDone(self):
4548
coroutine = Coroutine( f )
4649
# It's a daemon thread
4750
self.assertTrue( coroutine.isDaemon())
48-
# It doesn't run until we call it.
51+
# It's alive
52+
self.assertTrue(coroutine.is_alive())
53+
# But it doesn't run until we call it.
4954
self.assertEqual(TestCoroutine.coroutineCalls, [] )
5055
# Each call gets one iteration
5156
coroutine.call()
@@ -113,17 +118,13 @@ def cofunc():
113118
#And running it has caused the result parameter to be checked correctly before the coroutine terminated
114119
self.assertFalse(coroutine.is_alive())
115120

116-
def testRunCoroutinesUntilFirstCompletes(self):
117-
def cofunc1():
118-
Coroutine.wait()
119-
def cofunc2():
120-
Coroutine.wait()
121-
Coroutine.wait()
122-
# Coroutine.runTillFirstCompletes
123-
pass
121+
def testRunCoroutinesUntilFirstCompletesOrAllComplete(self):
122+
coroutine = Coroutine.runTillFirstCompletes(Coroutine(TestCoroutine.dummyCoroutineFunc,1,3),
123+
Coroutine(TestCoroutine.dummyCoroutineFunc,1,6))
124+
for i in range(1,10):
125+
coroutine.call()
126+
self.assertEquals(TestCoroutine.coroutineCalls, [1,1,2,2])
124127

125-
def testRunCoroutinesUntilAllComplete(self):
126-
pass
127128

128129

129130

0 commit comments

Comments
 (0)