concurrent_worker 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07268e6a9729fb2b470926764e1975ee7305c5fb9689412436b3d00c0dbcd30b
4
- data.tar.gz: e121b8aa8c4aacec697282f6efd07dbc0b8e968ec22d79d2e092bf173ea29dc7
3
+ metadata.gz: c743d7ebe52dcc21dcb90529e65d3cd0bbadf66a29dbbe16f8245f3c764cb787
4
+ data.tar.gz: f6d17a27e1b0666e896ebfeecf1b618ed2d2be87f5e9801899b3387ed4619469
5
5
  SHA512:
6
- metadata.gz: a26ace3f114dcefbfac75c354237b9180ee6f0b0f2d09b77eee265af845d3a1e027c7792c306e68a9b8c1e6b13599117d4c491aff8b6f1cb51f26debae015cec
7
- data.tar.gz: e2b7e20256f2fb68c18915132027df1ef002babf65bbda4da3495b07c289ad5f2c6d76c0c829245316d89c13804c3deded25c5144f6ba5ca52356b12a1f7c4ec
6
+ metadata.gz: 8843c5397cfd752204733a1b5f51f7fa9e924c5a7074ccb41b40f32320ef9a69680b16f1bd65dc9deec731f3ea155c3a8b832faf143499df9dc53525dfaf8d85
7
+ data.tar.gz: 979d6dd58b496f055a0647f8ff2a531e209c309d7475589998918c09e287b01b031bf0cabc16c7ba12e03dce91448ede61648469f0b55cf5fae8796fb3d6a811
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- concurrent_worker (0.2.2)
4
+ concurrent_worker (0.2.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -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, :req_queue_max
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
- @req_queue_max = @options[:req_queue_max] || 2
86
+ @snd_queue_max = @options[:snd_queue_max] || 2
73
87
  @req_counter = RequestCounter.new
74
-
75
- if @options[:type] == :process
76
- Worker.include ConcurrentProcess
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
- Worker.include ConcurrentThread
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
- unless @loop_block
130
- set_block(:loop_block) do
131
- loop do
132
- break if (req = receive_req).empty?
133
- (args, work_block) = req
134
- if work_block
135
- set_block(:work_block, &work_block)
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
- unless @base_block
143
- set_block(:base_block) do
144
- yield_loop_block
145
- end
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(@req_queue_max)
157
- send_req([args, work_block])
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
- send_req([])
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
- begin
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
- @thread = Thread.new do
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
- begin
288
- #called from main process only
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
- @thread && @thread.join
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
- @array_mutex = Mutex.new
330
- @ready_queue = Queue.new
331
-
332
- @result_callbacks = []
333
- @callback_queue = Queue.new
334
- @callback_thread = Thread.new do
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 = @req_queue.pop).empty?
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
- nw = deploy_worker
355
- nw.req_queue_max.times do
356
- @ready_queue.push(nw)
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 (w = @ready_queue.pop).kind_of?(Array)
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 delete(arg)
368
- @array_mutex.synchronize do
369
- super(arg)
370
- end
371
- end
372
- def push(arg)
373
- @array_mutex.synchronize do
374
- super(arg)
375
- end
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 need_new_worker?
389
- @array_mutex.synchronize do
390
- self.size < @max_num && self.select{ |w| w.req_counter.size == 0 }.empty?
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], req_queue_max: @req_queue_max, &@work_block)
414
+ w = Worker.new(*@args, type: @options[:type], snd_queue_max: @snd_queue_max, &@work_block)
407
415
  w.add_callback do |arg|
408
- @callback_queue.push([arg])
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
- @req_queue.push(req)
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 * @req_queue_max)
441
+ @req_counter.wait(@max_num * @snd_queue_max)
435
442
  @req_counter.push(true)
436
- @req_queue.push([args, work_block])
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
- @callback_queue.push([])
443
- @callback_thread.join
444
- @req_queue.push([])
445
- @req_thread.join
449
+ @rcv_queue.push([])
450
+ @rcv_thread.join
451
+ @snd_queue.push([])
452
+ @snd_thread.join
446
453
  end
447
454
  end
448
455
 
@@ -1,3 +1,3 @@
1
1
  module ConcurrentWorker
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent_worker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - dddogdiamond