Skip to content

Commit 2cf0c87

Browse files
author
Charles Weir
committed
cw: Added withTimeout to Coroutine
1 parent c616647 commit 2cf0c87

2 files changed

Lines changed: 36 additions & 5 deletions

File tree

BrickPython/Coroutine.py

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

1717
class Coroutine( threading.Thread ):
1818
def __init__(self, func, *args, **kwargs):
19-
print "Coroutine: %r %r" % (args, kwargs)
2019
threading.Thread.__init__(self)
2120
self.args = args
2221
self.kwargs = kwargs
@@ -98,7 +97,7 @@ def waitMilliseconds(timeMillis):
9897
@staticmethod
9998
def runTillFirstCompletes(*coroutines):
10099
def runTillFirstCompletesFunc(*coroutineList):
101-
while True:
100+
while all(c.is_alive() for c in coroutineList):
102101
for c in coroutineList:
103102
c.call()
104103
if not c.is_alive():
@@ -111,6 +110,25 @@ def runTillFirstCompletesFunc(*coroutineList):
111110
result = Coroutine(runTillFirstCompletesFunc, *coroutines)
112111
return result
113112

113+
@staticmethod
114+
def runTillAllComplete(*coroutines):
115+
def runTillAllCompleteFunc(*coroutineList):
116+
while any(c.is_alive() for c in coroutineList):
117+
for c in coroutineList:
118+
c.call()
119+
Coroutine.wait()
120+
121+
result = Coroutine(runTillAllCompleteFunc, *coroutines)
122+
return result
123+
124+
def withTimeout(self, timeoutMillis):
125+
'''Answers this coroutine, decorated with a timeout that stops it if called after timeoutMillis has elapsed.
126+
'''
127+
def timeoutFunc(timeoutMillis):
128+
Coroutine.waitMilliseconds(timeoutMillis)
129+
result = Coroutine.runTillFirstCompletes(self, Coroutine(timeoutFunc, timeoutMillis))
130+
return result
131+
114132
#
115133
# self.scheduler.coroutines.remove( self )
116134
# self.scheduler.semaphore.release()

test/TestCoroutine.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ class TestCoroutine(unittest.TestCase):
2222
coroutineCalls = []
2323
@staticmethod
2424
def dummyCoroutineFunc(start=1, end=5):
25-
logging.debug( "in dummyCoroutineFunc %d %d" %(start, end) )
2625
for i in range(start, end):
2726
TestCoroutine.coroutineCalls.append(i)
2827
Coroutine.wait();
@@ -100,7 +99,7 @@ def dummyCoroutineFuncWaiting1Sec():
10099

101100
def testCoroutineCanHaveParameters(self):
102101
def func(*args, **kwargs):
103-
self.assertEquals(args, (1))
102+
self.assertEquals(args, (1,))
104103
self.assertEquals(kwargs, {"extra": 2})
105104
coroutine = Coroutine(func, 1, extra=2)
106105
coroutine.call()
@@ -118,13 +117,27 @@ def cofunc():
118117
#And running it has caused the result parameter to be checked correctly before the coroutine terminated
119118
self.assertFalse(coroutine.is_alive())
120119

121-
def testRunCoroutinesUntilFirstCompletesOrAllComplete(self):
120+
def testRunCoroutinesUntilFirstCompletes(self):
122121
coroutine = Coroutine.runTillFirstCompletes(Coroutine(TestCoroutine.dummyCoroutineFunc,1,3),
123122
Coroutine(TestCoroutine.dummyCoroutineFunc,1,6))
124123
for i in range(1,10):
125124
coroutine.call()
126125
self.assertEquals(TestCoroutine.coroutineCalls, [1,1,2,2])
127126

127+
def testRunCoroutinesUntilAllComplete(self):
128+
coroutine = Coroutine.runTillAllComplete(Coroutine(TestCoroutine.dummyCoroutineFunc,1,3),
129+
Coroutine(TestCoroutine.dummyCoroutineFunc,1,6))
130+
for i in range(1,10):
131+
coroutine.call()
132+
self.assertEquals(TestCoroutine.coroutineCalls, [1,1,2,2,3,4,5])
133+
134+
def testWithTimeout(self):
135+
Coroutine.currentTimeMillis = Mock(side_effect = [1,10,500,1200])
136+
coroutine = Coroutine(TestCoroutine.dummyCoroutineFunc,1,20).withTimeout(1000)
137+
for i in range(1,20):
138+
coroutine.call()
139+
self.assertEquals(TestCoroutine.coroutineCalls, [1,2,3])
140+
128141

129142

130143

0 commit comments

Comments
 (0)