concurrent_worker 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/concurrent_worker.rb +140 -133
- data/lib/concurrent_worker/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c743d7ebe52dcc21dcb90529e65d3cd0bbadf66a29dbbe16f8245f3c764cb787
|
4
|
+
data.tar.gz: f6d17a27e1b0666e896ebfeecf1b618ed2d2be87f5e9801899b3387ed4619469
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8843c5397cfd752204733a1b5f51f7fa9e924c5a7074ccb41b40f32320ef9a69680b16f1bd65dc9deec731f3ea155c3a8b832faf143499df9dc53525dfaf8d85
|
7
|
+
data.tar.gz: 979d6dd58b496f055a0647f8ff2a531e209c309d7475589998918c09e287b01b031bf0cabc16c7ba12e03dce91448ede61648469f0b55cf5fae8796fb3d6a811
|
data/Gemfile.lock
CHANGED
data/lib/concurrent_worker.rb
CHANGED
@@ -12,11 +12,11 @@ module ConcurrentWorker
|
|
12
12
|
def push(args)
|
13
13
|
@count.push(args)
|
14
14
|
end
|
15
|
-
|
16
15
|
def pop
|
17
16
|
@count.pop
|
18
17
|
@com.push([])
|
19
18
|
end
|
19
|
+
|
20
20
|
def wait(n)
|
21
21
|
return if @count.size <= n
|
22
22
|
while @com.pop
|
@@ -31,6 +31,10 @@ module ConcurrentWorker
|
|
31
31
|
@count.close
|
32
32
|
end
|
33
33
|
|
34
|
+
def closed?
|
35
|
+
@count.closed?
|
36
|
+
end
|
37
|
+
|
34
38
|
def rest
|
35
39
|
result = []
|
36
40
|
until @count.empty?
|
@@ -58,7 +62,17 @@ module ConcurrentWorker
|
|
58
62
|
# so that they can share instance variables:@xxxx.
|
59
63
|
#
|
60
64
|
|
61
|
-
attr_reader :req_counter, :
|
65
|
+
attr_reader :req_counter, :snd_queue_max
|
66
|
+
|
67
|
+
def queue_closed?
|
68
|
+
@req_counter.closed?
|
69
|
+
end
|
70
|
+
def queue_empty?
|
71
|
+
!queue_closed? && @req_counter.size == 0
|
72
|
+
end
|
73
|
+
def queue_available?
|
74
|
+
!queue_closed? && @req_counter.size < @snd_queue_max
|
75
|
+
end
|
62
76
|
|
63
77
|
def initialize(*args, **options, &work_block)
|
64
78
|
@args = args
|
@@ -69,13 +83,22 @@ module ConcurrentWorker
|
|
69
83
|
@result_callbacks = []
|
70
84
|
@retired_callbacks = []
|
71
85
|
|
72
|
-
@
|
86
|
+
@snd_queue_max = @options[:snd_queue_max] || 2
|
73
87
|
@req_counter = RequestCounter.new
|
74
|
-
|
75
|
-
|
76
|
-
|
88
|
+
|
89
|
+
case @options[:type]
|
90
|
+
when :process
|
91
|
+
class << self
|
92
|
+
include ConcurrentProcess
|
93
|
+
end
|
94
|
+
when :thread
|
95
|
+
class << self
|
96
|
+
include ConcurrentThread
|
97
|
+
end
|
77
98
|
else
|
78
|
-
|
99
|
+
class << self
|
100
|
+
include ConcurrentThread
|
101
|
+
end
|
79
102
|
end
|
80
103
|
end
|
81
104
|
|
@@ -88,6 +111,7 @@ module ConcurrentWorker
|
|
88
111
|
@result_callbacks.each do |callback|
|
89
112
|
callback.call(args)
|
90
113
|
end
|
114
|
+
@req_counter.pop
|
91
115
|
end
|
92
116
|
|
93
117
|
def add_retired_callback(&callback)
|
@@ -122,43 +146,55 @@ module ConcurrentWorker
|
|
122
146
|
end
|
123
147
|
end
|
124
148
|
end
|
125
|
-
|
126
|
-
def run
|
127
|
-
@state = :run
|
128
149
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
end
|
137
|
-
send_res(yield_work_block(args))
|
150
|
+
def set_default_loop_block
|
151
|
+
set_block(:loop_block) do
|
152
|
+
loop do
|
153
|
+
break if (req = receive_req).empty?
|
154
|
+
(args, work_block) = req
|
155
|
+
if work_block
|
156
|
+
set_block(:work_block, &work_block)
|
138
157
|
end
|
158
|
+
send_res(yield_work_block(args))
|
139
159
|
end
|
140
160
|
end
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
161
|
+
end
|
162
|
+
|
163
|
+
def set_default_base_block
|
164
|
+
set_block(:base_block) do
|
165
|
+
yield_loop_block
|
146
166
|
end
|
147
|
-
|
167
|
+
end
|
168
|
+
|
169
|
+
def run
|
170
|
+
@state = :run
|
171
|
+
set_default_loop_block unless @loop_block
|
172
|
+
set_default_base_block unless @base_block
|
148
173
|
cncr_block
|
149
174
|
end
|
150
|
-
|
151
175
|
|
152
176
|
def req(*args, &work_block)
|
153
177
|
unless @state == :run
|
154
178
|
run
|
155
179
|
end
|
156
|
-
@req_counter.wait(@
|
157
|
-
|
180
|
+
@req_counter.wait(@snd_queue_max)
|
181
|
+
begin
|
182
|
+
@req_counter.push([args, work_block])
|
183
|
+
send_req([args, work_block])
|
184
|
+
true
|
185
|
+
rescue ClosedQueueError, IOError
|
186
|
+
false
|
187
|
+
end
|
158
188
|
end
|
159
189
|
|
160
190
|
def quit
|
161
|
-
|
191
|
+
begin
|
192
|
+
@req_counter.push([])
|
193
|
+
send_req([])
|
194
|
+
true
|
195
|
+
rescue ClosedQueueError, IOError
|
196
|
+
false
|
197
|
+
end
|
162
198
|
end
|
163
199
|
|
164
200
|
def join
|
@@ -184,13 +220,7 @@ module ConcurrentWorker
|
|
184
220
|
end
|
185
221
|
|
186
222
|
def send_req(args)
|
187
|
-
|
188
|
-
@req_counter.push(args)
|
189
|
-
@thread_channel.push(args)
|
190
|
-
true
|
191
|
-
rescue ClosedQueueError
|
192
|
-
false
|
193
|
-
end
|
223
|
+
@thread_channel.push(args)
|
194
224
|
end
|
195
225
|
|
196
226
|
def receive_req
|
@@ -199,7 +229,6 @@ module ConcurrentWorker
|
|
199
229
|
|
200
230
|
def send_res(args)
|
201
231
|
call_result_callbacks(args)
|
202
|
-
@req_counter.pop
|
203
232
|
end
|
204
233
|
|
205
234
|
def wait_cncr_proc
|
@@ -245,24 +274,10 @@ module ConcurrentWorker
|
|
245
274
|
def close
|
246
275
|
[@wio, @rio].map(&:close)
|
247
276
|
end
|
248
|
-
|
249
277
|
end
|
250
|
-
|
251
|
-
def cncr_block
|
252
|
-
@ipc_channel = IPCDuplexChannel.new
|
253
|
-
@c_pid = fork do
|
254
|
-
@ipc_channel.choose_io
|
255
|
-
begin
|
256
|
-
yield_base_block
|
257
|
-
rescue
|
258
|
-
@ipc_channel.send($!)
|
259
|
-
ensure
|
260
|
-
@ipc_channel.send(:worker_loop_finished)
|
261
|
-
end
|
262
|
-
end
|
263
|
-
@ipc_channel.choose_io
|
264
278
|
|
265
|
-
|
279
|
+
def set_rcv_thread
|
280
|
+
Thread.new do
|
266
281
|
begin
|
267
282
|
loop do
|
268
283
|
result = @ipc_channel.recv
|
@@ -270,28 +285,37 @@ module ConcurrentWorker
|
|
270
285
|
raise result if result.kind_of?(Exception)
|
271
286
|
|
272
287
|
call_result_callbacks(result)
|
273
|
-
@req_counter.pop
|
274
288
|
end
|
275
289
|
rescue
|
276
290
|
Thread.pass
|
277
291
|
raise $!
|
278
292
|
ensure
|
279
|
-
@ipc_channel.close
|
280
293
|
@req_counter.close
|
294
|
+
@ipc_channel.close
|
281
295
|
call_retired_callbacks
|
282
296
|
end
|
283
297
|
end
|
284
298
|
end
|
299
|
+
|
300
|
+
def cncr_block
|
301
|
+
@ipc_channel = IPCDuplexChannel.new
|
302
|
+
@c_pid = fork do
|
303
|
+
@ipc_channel.choose_io
|
304
|
+
begin
|
305
|
+
yield_base_block
|
306
|
+
rescue
|
307
|
+
@ipc_channel.send($!)
|
308
|
+
ensure
|
309
|
+
@ipc_channel.send(:worker_loop_finished)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
@ipc_channel.choose_io
|
313
|
+
@rcv_thread = set_rcv_thread
|
314
|
+
end
|
285
315
|
|
286
316
|
def send_req(args)
|
287
|
-
|
288
|
-
|
289
|
-
@req_counter.push(args)
|
290
|
-
@ipc_channel.send(args)
|
291
|
-
true
|
292
|
-
rescue ClosedQueueError, IOError
|
293
|
-
false
|
294
|
-
end
|
317
|
+
#called from main process only
|
318
|
+
@ipc_channel.send(args)
|
295
319
|
end
|
296
320
|
|
297
321
|
def receive_req
|
@@ -309,86 +333,70 @@ module ConcurrentWorker
|
|
309
333
|
Process.waitpid(@c_pid)
|
310
334
|
rescue Errno::ECHILD
|
311
335
|
end
|
312
|
-
@
|
336
|
+
@rcv_thread && @rcv_thread.join
|
313
337
|
end
|
314
338
|
end
|
315
339
|
|
316
340
|
|
317
341
|
|
318
342
|
class WorkerPool < Array
|
319
|
-
def initialize(*args, **options, &work_block)
|
320
|
-
@args = args
|
321
|
-
|
322
|
-
@options = options
|
323
|
-
@max_num = @options[:pool_max] || 8
|
324
|
-
@set_blocks = []
|
325
|
-
if work_block
|
326
|
-
@set_blocks.push([:work_block, work_block])
|
327
|
-
end
|
328
343
|
|
329
|
-
|
330
|
-
@
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
loop do
|
336
|
-
break if (result = @callback_queue.pop).empty?
|
337
|
-
@result_callbacks.each do |callback|
|
338
|
-
callback.call(result[0])
|
339
|
-
end
|
340
|
-
@req_counter.pop
|
341
|
-
end
|
342
|
-
end
|
343
|
-
@req_queue_max = @options[:req_queue_max]||2
|
344
|
-
|
345
|
-
@req_queue = Queue.new
|
346
|
-
@req_counter = RequestCounter.new
|
347
|
-
@req_thread = Thread.new do
|
344
|
+
def need_new_worker?
|
345
|
+
self.size < @max_num && self.select{ |w| w.queue_empty? }.empty?
|
346
|
+
end
|
347
|
+
|
348
|
+
def set_snd_thread
|
349
|
+
Thread.new do
|
348
350
|
loop do
|
349
|
-
break if (req = @
|
350
|
-
|
351
|
-
w = nil
|
351
|
+
break if (req = @snd_queue.pop).empty?
|
352
352
|
loop do
|
353
|
+
delete_if{ |w| w.queue_closed? }
|
353
354
|
if need_new_worker?
|
354
|
-
|
355
|
-
|
356
|
-
@ready_queue.push(
|
355
|
+
w = deploy_worker
|
356
|
+
w.snd_queue_max.times do
|
357
|
+
@ready_queue.push(w)
|
357
358
|
end
|
358
359
|
end
|
359
|
-
break if
|
360
|
-
break if w.req(*req[0], &req[1])
|
360
|
+
break if @ready_queue.pop.req(*req[0], &req[1])
|
361
361
|
end
|
362
|
-
break if w.kind_of?(Array)
|
363
362
|
end
|
364
363
|
end
|
365
364
|
end
|
366
365
|
|
367
|
-
def
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
end
|
377
|
-
def shift
|
378
|
-
@array_mutex.synchronize do
|
379
|
-
super
|
380
|
-
end
|
381
|
-
end
|
382
|
-
def empty?
|
383
|
-
@array_mutex.synchronize do
|
384
|
-
super
|
366
|
+
def set_rcv_thread
|
367
|
+
Thread.new do
|
368
|
+
loop do
|
369
|
+
break if (result = @rcv_queue.pop).empty?
|
370
|
+
@result_callbacks.each do |callback|
|
371
|
+
callback.call(result[0])
|
372
|
+
end
|
373
|
+
@req_counter.pop
|
374
|
+
end
|
385
375
|
end
|
386
376
|
end
|
387
|
-
|
388
|
-
def
|
389
|
-
@
|
390
|
-
|
377
|
+
|
378
|
+
def initialize(*args, **options, &work_block)
|
379
|
+
@args = args
|
380
|
+
|
381
|
+
@options = options
|
382
|
+
@max_num = @options[:pool_max] || 8
|
383
|
+
@set_blocks = []
|
384
|
+
if work_block
|
385
|
+
@set_blocks.push([:work_block, work_block])
|
391
386
|
end
|
387
|
+
|
388
|
+
@ready_queue = Queue.new
|
389
|
+
|
390
|
+
@result_callbacks = []
|
391
|
+
|
392
|
+
@snd_queue_max = @options[:snd_queue_max]||2
|
393
|
+
@req_counter = RequestCounter.new
|
394
|
+
|
395
|
+
@snd_queue = Queue.new
|
396
|
+
@snd_thread = set_snd_thread
|
397
|
+
|
398
|
+
@rcv_queue = Queue.new
|
399
|
+
@rcv_thread = set_rcv_thread
|
392
400
|
end
|
393
401
|
|
394
402
|
def add_callback(&callback)
|
@@ -403,18 +411,17 @@ module ConcurrentWorker
|
|
403
411
|
|
404
412
|
|
405
413
|
def deploy_worker
|
406
|
-
w = Worker.new(*@args, type: @options[:type],
|
414
|
+
w = Worker.new(*@args, type: @options[:type], snd_queue_max: @snd_queue_max, &@work_block)
|
407
415
|
w.add_callback do |arg|
|
408
|
-
@
|
416
|
+
@rcv_queue.push([arg])
|
409
417
|
@ready_queue.push(w)
|
410
418
|
end
|
411
419
|
|
412
420
|
w.add_retired_callback do
|
413
421
|
w.req_counter.rest.each do
|
414
422
|
|req|
|
415
|
-
@
|
423
|
+
@snd_queue.push(req)
|
416
424
|
end
|
417
|
-
self.delete(w)
|
418
425
|
@ready_queue.push(w)
|
419
426
|
end
|
420
427
|
|
@@ -431,18 +438,18 @@ module ConcurrentWorker
|
|
431
438
|
end
|
432
439
|
|
433
440
|
def req(*args, &work_block)
|
434
|
-
@req_counter.wait(@max_num * @
|
441
|
+
@req_counter.wait(@max_num * @snd_queue_max)
|
435
442
|
@req_counter.push(true)
|
436
|
-
@
|
443
|
+
@snd_queue.push([args, work_block])
|
437
444
|
end
|
438
445
|
|
439
446
|
def join
|
440
447
|
@req_counter.wait(0)
|
441
448
|
self.shift.join until self.empty?
|
442
|
-
@
|
443
|
-
@
|
444
|
-
@
|
445
|
-
@
|
449
|
+
@rcv_queue.push([])
|
450
|
+
@rcv_thread.join
|
451
|
+
@snd_queue.push([])
|
452
|
+
@snd_thread.join
|
446
453
|
end
|
447
454
|
end
|
448
455
|
|