forked from noisebridge/nb_whiteboarding
-
Notifications
You must be signed in to change notification settings - Fork 4
/
force_order_in_concurrency.py
92 lines (71 loc) · 2.32 KB
/
force_order_in_concurrency.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
"""
12/12/2018: Problem 5
CTCI concurrency problem: Given a class that has methods `method1()`,
`method2()`, and `method3()`, each of these methods will be run on a
separate thread. Devise a mechanism where `method2()` only starts
after `method1()` is finished and `method3()` starts only after
`method2()` is finished.
"""
class Foo:
def method1(self):
print("Called method 1")
def method2(self):
print("Called method 2")
def method3(self):
print("Called method 3")
def runMethodsForcingOrderInConcurrency(loopForever = False):
"""
Three methods of an object, each called in separate threads,
are forced to be called in a set sequence
(i.e., method1, then method2, then method3).
If specified in the parameter,
this sequence will repeat in a cycle forever.
Author: Eugene Ma
"""
import threading
foo = Foo()
stage = 0
stageLock = threading.RLock()
stageCond = threading.Condition(stageLock)
def makeTarget(preReqStage, func, nextStage):
def target():
nonlocal stage
print('In thread: {0}'.format(threading.current_thread().name))
while True:
stageLock.acquire()
try:
while True:
if stage == preReqStage:
func()
stage = nextStage
stageCond.notify_all()
break;
else:
stageCond.wait()
finally:
stageLock.release()
if not loopForever:
break;
return target
funcs = [
lambda: foo.method1(),
lambda: foo.method2(),
lambda: foo.method3(),
]
threads = []
for i in range(3):
nextStage = i + 1
if loopForever:
nextStage %= 3
thread = threading.Thread(target=makeTarget(i, funcs[i], nextStage))
threads.append(thread)
import random
random.shuffle(threads)
for thread in threads:
thread.start()
for thread in threads:
thread.join()
if __name__ == '__main__':
# TODO: Pick one:
runMethodsForcingOrderInConcurrency(False)
#runMethodsForcingOrderInConcurrency(True) # Loop forever