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 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