parallel 1.2.4 → 1.3.0

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
  SHA1:
3
- metadata.gz: f6ea4deb03b39b10b4efc968f86c86d8fba2c42f
4
- data.tar.gz: b32876b86f9acc449bb45d28b154708f9af0dee1
3
+ metadata.gz: d2df287a5ddf0d25ea8f7ab32b06e9d71046eef8
4
+ data.tar.gz: f4df68005a7a134922caa0dd7458a5ad48ebb14f
5
5
  SHA512:
6
- metadata.gz: 92021663b44c16d0ce0f9dfa0c616f3852f9e2a6f7c85521c06283f2fd5daad75f7dbf95703241c926b71eb98a44619eefdcc62d3039e4311d8ba4389fb06649
7
- data.tar.gz: c48fdaebf240f24722a41868688e0373349f78eb1de8e9329cdd0e458cdaf0458e1cbc6cbbfd4f3b5707c5363706e4755ed66c543332c03b39b2be909ccd0132
6
+ metadata.gz: 73b00704981e7a87f6c6448cc80759d4e4bbd62c07bc852c84c81da631480571f7acf1cff261eb72f3c2532cee96fb12670329ac9acf35c4f7c48272834ea875
7
+ data.tar.gz: e975280dc1eb0825479e03e2d433e89021ec336a4bc1ab3e05319afccf73d3c67f190938df1a3faeb5c9c8d1335a0ac64b67c9982c1e19936c34a83f120bdfc8
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,4 +1,3 @@
1
- require 'thread' # to get Thread.exclusive
2
1
  require 'rbconfig'
3
2
  require 'parallel/version'
4
3
  require 'parallel/processor_count'
@@ -15,6 +14,8 @@ module Parallel
15
14
  class Kill < StandardError
16
15
  end
17
16
 
17
+ Stop = Object.new
18
+
18
19
  INTERRUPT_SIGNAL = :SIGINT
19
20
 
20
21
  class ExceptionWrapper
@@ -47,9 +48,9 @@ module Parallel
47
48
  # process died
48
49
  end
49
50
 
50
- def work(index)
51
+ def work(data)
51
52
  begin
52
- Marshal.dump(index, write)
53
+ Marshal.dump(data, write)
53
54
  rescue Errno::EPIPE
54
55
  raise DeadWorker
55
56
  end
@@ -62,6 +63,66 @@ module Parallel
62
63
  end
63
64
  end
64
65
 
66
+ class ItemWrapper
67
+ def initialize(array, mutex)
68
+ @lambda = (array.respond_to?(:call) && array) || queue_wrapper(array)
69
+ @items = array.to_a unless @lambda # turn Range and other Enumerable-s into an Array
70
+ @mutex = mutex
71
+ @index = -1
72
+ end
73
+
74
+ def producer?
75
+ @lambda
76
+ end
77
+
78
+ def each_with_index(&block)
79
+ if producer?
80
+ loop do
81
+ item, index = self.next
82
+ break unless index
83
+ yield(item, index)
84
+ end
85
+ else
86
+ @items.each_with_index(&block)
87
+ end
88
+ end
89
+
90
+ def next
91
+ if producer?
92
+ # - index and item stay in sync
93
+ # - do not call lambda after it has returned Stop
94
+ item, index = @mutex.synchronize do
95
+ return if @stopped
96
+ item = @lambda.call
97
+ @stopped = (item == Parallel::Stop)
98
+ return if @stopped
99
+ [item, @index += 1]
100
+ end
101
+ else
102
+ index = @mutex.synchronize { @index += 1 }
103
+ return if index >= size
104
+ item = @items[index]
105
+ end
106
+ [item, index]
107
+ end
108
+
109
+ def size
110
+ @items.size
111
+ end
112
+
113
+ def pack(item, index)
114
+ producer? ? [item, index] : index
115
+ end
116
+
117
+ def unpack(data)
118
+ producer? ? data : [@items[data], data]
119
+ end
120
+
121
+ def queue_wrapper(array)
122
+ array.is_a?(::Queue) && lambda { array.pop(false) }
123
+ end
124
+ end
125
+
65
126
  class << self
66
127
  def in_threads(options={:count => 2})
67
128
  count, options = extract_count_from_options(options)
@@ -96,8 +157,7 @@ module Parallel
96
157
  end
97
158
 
98
159
  def map(array, options = {}, &block)
99
- array = array.to_a # turn Range and other Enumerable-s into an Array
100
- options[:mutex] ||= Mutex.new
160
+ options[:mutex] = Mutex.new
101
161
 
102
162
  if RUBY_PLATFORM =~ /java/ and not options[:in_processes]
103
163
  method = :in_threads
@@ -114,26 +174,36 @@ module Parallel
114
174
  size = 0
115
175
  end
116
176
  end
117
- size = [array.size, size].min
177
+
178
+ items = ItemWrapper.new(array, options[:mutex])
179
+
180
+ size = [items.producer? ? size : items.size, size].min
118
181
 
119
182
  options[:return_results] = (options[:preserve_results] != false || !!options[:finish])
120
- add_progress_bar!(array, options)
183
+ add_progress_bar!(items, options)
121
184
 
122
185
  if size == 0
123
- work_direct(array, options, &block)
186
+ work_direct(items, options, &block)
124
187
  elsif method == :in_threads
125
- work_in_threads(array, options.merge(:count => size), &block)
188
+ work_in_threads(items, options.merge(:count => size), &block)
126
189
  else
127
- work_in_processes(array, options.merge(:count => size), &block)
190
+ work_in_processes(items, options.merge(:count => size), &block)
128
191
  end
129
192
  end
130
193
 
131
- def add_progress_bar!(array, options)
194
+ def map_with_index(array, options={}, &block)
195
+ map(array, options.merge(:with_index => true), &block)
196
+ end
197
+
198
+ private
199
+
200
+ def add_progress_bar!(items, options)
132
201
  if title = options[:progress]
202
+ raise "Progressbar and producers don't mix" if items.producer?
133
203
  require 'ruby-progressbar'
134
204
  progress = ProgressBar.create(
135
205
  :title => title,
136
- :total => array.size,
206
+ :total => items.size,
137
207
  :format => '%t |%E | %B | %a'
138
208
  )
139
209
  old_finish = options[:finish]
@@ -144,15 +214,10 @@ module Parallel
144
214
  end
145
215
  end
146
216
 
147
- def map_with_index(array, options={}, &block)
148
- map(array, options.merge(:with_index => true), &block)
149
- end
150
-
151
- private
152
217
 
153
- def work_direct(array, options)
218
+ def work_direct(items, options)
154
219
  results = []
155
- array.each_with_index do |e,i|
220
+ items.each_with_index do |e,i|
156
221
  results << (options[:with_index] ? yield(e,i) : yield(e))
157
222
  end
158
223
  results
@@ -160,20 +225,18 @@ module Parallel
160
225
 
161
226
  def work_in_threads(items, options, &block)
162
227
  results = []
163
- current = -1
164
228
  exception = nil
165
229
 
166
230
  in_threads(options[:count]) do
167
231
  # as long as there are more items, work on one of them
168
232
  loop do
169
233
  break if exception
170
-
171
- index = Thread.exclusive { current += 1 }
172
- break if index >= items.size
234
+ item, index = items.next
235
+ break unless index
173
236
 
174
237
  begin
175
- results[index] = with_instrumentation items[index], index, options do
176
- call_with_index(items, index, options, &block)
238
+ results[index] = with_instrumentation item, index, options do
239
+ call_with_index(item, index, options, &block)
177
240
  end
178
241
  rescue StandardError => e
179
242
  exception = e
@@ -187,9 +250,9 @@ module Parallel
187
250
 
188
251
  def work_in_processes(items, options, &blk)
189
252
  workers = create_workers(items, options, &blk)
190
- current_index = -1
191
253
  results = []
192
254
  exception = nil
255
+
193
256
  kill_on_ctrl_c(workers.map(&:pid)) do
194
257
  in_threads(options[:count]) do |i|
195
258
  worker = workers[i]
@@ -198,11 +261,11 @@ module Parallel
198
261
  begin
199
262
  loop do
200
263
  break if exception
201
- index = Thread.exclusive{ current_index += 1 }
202
- break if index >= items.size
264
+ item, index = items.next
265
+ break unless index
203
266
 
204
- output = with_instrumentation items[index], index, options do
205
- worker.work(index)
267
+ output = with_instrumentation item, index, options do
268
+ worker.work(items.pack(item, index))
206
269
  end
207
270
 
208
271
  if ExceptionWrapper === output
@@ -264,9 +327,10 @@ module Parallel
264
327
 
265
328
  def process_incoming_jobs(read, write, items, options, &block)
266
329
  while !read.eof?
267
- index = Marshal.load(read)
330
+ data = Marshal.load(read)
331
+ item, index = items.unpack(data)
268
332
  result = begin
269
- call_with_index(items, index, options, &block)
333
+ call_with_index(item, index, options, &block)
270
334
  rescue StandardError => e
271
335
  ExceptionWrapper.new(e)
272
336
  end
@@ -355,8 +419,8 @@ module Parallel
355
419
  end
356
420
  end
357
421
 
358
- def call_with_index(array, index, options, &block)
359
- args = [array[index]]
422
+ def call_with_index(item, index, options, &block)
423
+ args = [item]
360
424
  args << index if options[:with_index]
361
425
  if options[:return_results]
362
426
  block.call(*args)
@@ -1,3 +1,3 @@
1
1
  module Parallel
2
- VERSION = Version = '1.2.4'
2
+ VERSION = Version = '1.3.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
@@ -30,7 +30,7 @@ cert_chain:
30
30
  F5etKHZg0j3eHO31/i2HnswY04lqGImUu6aM5EnijFTB7PPW2KwKKM4+kKDYFdlw
31
31
  /0WV1Ng2/Y6qsHwmqGg2VlYj2h4=
32
32
  -----END CERTIFICATE-----
33
- date: 2014-08-17 00:00:00.000000000 Z
33
+ date: 2014-08-30 00:00:00.000000000 Z
34
34
  dependencies: []
35
35
  description:
36
36
  email: michael@grosser.it
metadata.gz.sig CHANGED
Binary file