/
process_pipeline_factory.py
82 lines (63 loc) · 2 KB
/
process_pipeline_factory.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
import time
import collections
import inspect
from multiprocessing import Process, Queue
from random import random
from parallel_pipeline_factory import ParallelPipelineFactory
class ProcessPipelineFactory(ParallelPipelineFactory):
def create_buffer(self):
return Queue()
def create_source(self, func):
return Source(func)
def create_filter(self, func):
return Filter(func)
def create_sink(self, func):
return Sink(func)
class Source(Process):
def __init__(self, func):
Process.__init__(self)
self.func = func
self.out_buffer = None
def run(self):
for token in self.func():
self.out_buffer.put(token)
sleep()
self.out_buffer.put(STOP_FLAG)
class Filter(Process):
def __init__(self, func):
Process.__init__(self)
self.in_buffer = None
self.out_buffer = None
self.func = func
# number of tokens popped from the input buffer each time
self.n_args = len(inspect.getargspec(func).args)
def run(self):
args = []
tokens = iter(self.in_buffer.get, STOP_FLAG)
for token in tokens:
if isinstance(token, collections.Iterable):
args.extend(token)
else:
args.append(token)
if len(args) == self.n_args:
result = self.func(*args)
self.out_buffer.put(result)
args = []
sleep()
# Put the STOP flag back to input for other filters
self.in_buffer.put(STOP_FLAG)
self.out_buffer.put(STOP_FLAG)
class Sink(Process):
def __init__(self, func):
Process.__init__(self)
self.in_buffer = None
self.func = func
def run(self):
tokens = iter(self.in_buffer.get, STOP_FLAG)
for token in tokens:
self.func(token)
sleep()
STOP_FLAG = StopIteration
MAX_SLEEP_SECONDS = 0.0001
def sleep():
time.sleep(random() * MAX_SLEEP_SECONDS)