76
76
signal.signal(signal.SIGINT, signal.SIG_IGN)
80
83
"""This class is used to execute tasks in series, and is more efficient
81
84
than Parallel, but is only appropriate for non-parallel builds. Only
149
154
task = self.requestQueue.get()
157
# The "None" value is used as a sentinel by
158
# ThreadPool.cleanup(). This indicates that there
159
# are no more tasks, so we should quit.
153
164
except KeyboardInterrupt:
170
181
self.resultsQueue = Queue.Queue(0)
172
183
# Create worker threads
173
185
for _ in range(num):
174
Worker(self.requestQueue, self.resultsQueue)
186
worker = Worker(self.requestQueue, self.resultsQueue)
187
self.workers.append(worker)
176
189
def put(self, obj):
177
190
"""Put task into request queue."""
182
195
return self.resultsQueue.get(block)
184
197
def preparation_failed(self, obj):
185
self.resultsQueue.put((obj, 0))
198
self.resultsQueue.put((obj, False))
202
Shuts down the thread pool, giving each worker thread a
203
chance to shut down gracefully.
205
# For each worker thread, put a sentinel "None" value
206
# on the requestQueue (indicating that there's no work
207
# to be done) so that each worker thread will get one and
208
# terminate gracefully.
209
for _ in self.workers:
210
self.requestQueue.put(None)
212
# Wait for all of the workers to terminate.
214
# If we don't do this, later Python versions (2.4, 2.5) often
215
# seem to raise exceptions during shutdown. This happens
216
# in requestQueue.get(), as an assertion failure that
217
# requestQueue.not_full is notified while not acquired,
218
# seemingly because the main thread has shut down (or is
219
# in the process of doing so) while the workers are still
220
# trying to pull sentinels off the requestQueue.
222
# Normally these terminations should happen fairly quickly,
223
# but we'll stick a one-second timeout on here just in case
225
for worker in self.workers:
188
230
"""This class is used to execute tasks in parallel, and is somewhat