simple-future 1.0.0.pre3 → 1.0.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 +4 -4
- data/.yardopts +3 -0
- data/doc/SimpleFuture.html +56 -81
- data/doc/SimpleFuture/ChildError.html +11 -18
- data/doc/SimpleFuture/Error.html +5 -5
- data/doc/SimpleFuture/ResultTypeError.html +6 -7
- data/doc/_index.html +2 -2
- data/doc/file.README.html +83 -87
- data/doc/index.html +83 -87
- data/doc/top-level-namespace.html +2 -2
- data/simple-future.gemspec +6 -3
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1df9f1b810af6a00ce3b5e97eaae569fab269360
|
4
|
+
data.tar.gz: 019574a38b467f2d60f6adb0692e96fb07a9b47f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 434b5e65ca6b30c698369d4564caae4fd1285f315d320c4a26301adeafe3c51ecb72108736a630b7e013e545ca146ed8ef12d724684f14609321f863bcb346f3
|
7
|
+
data.tar.gz: 1292d0877b4f0cfffacf9662490354a153604e66849e239d4456af839b4adcfed1f28df49adf1533fb6594a33e3a88da25f0ec290671fbb99d4ac67ed951138c
|
data/.yardopts
ADDED
data/doc/SimpleFuture.html
CHANGED
@@ -101,21 +101,21 @@
|
|
101
101
|
|
102
102
|
<h2>Overview</h2><div class="docstring">
|
103
103
|
<div class="discussion">
|
104
|
-
|
105
|
-
|
106
|
-
that
|
107
|
-
be passed to the constructor:</p>
|
104
|
+
<p>A container holding the (eventual) result of a forked child process
|
105
|
+
once that process finishes. The child process executes the code
|
106
|
+
block that must be passed to the constructor:</p>
|
108
107
|
|
109
108
|
<pre class="code ruby"><code class="ruby"> sf = SimpleFuture.new { do_slow_thing }
|
110
109
|
... do stuff ...
|
111
|
-
use(sf.value)
|
110
|
+
use(sf.value)
|
111
|
+
</code></pre>
|
112
112
|
|
113
113
|
<p>The code block <strong>must</strong> return a value that can be encoded by
|
114
114
|
<code>Marshal</code> and <strong>must not</strong> exit prematurely.</p>
|
115
115
|
|
116
116
|
<p>Exceptions thrown inside the block will trigger a
|
117
|
-
<code>SimpleFuture::ChildError</code> in the parent process but that
|
118
|
-
|
117
|
+
<code>SimpleFuture::ChildError</code> in the parent process but that exception
|
118
|
+
will contain the original in its <code>cause</code> field.</p>
|
119
119
|
|
120
120
|
|
121
121
|
</div>
|
@@ -165,8 +165,7 @@ exception will contain the original in its <code>cause</code> field.</p>
|
|
165
165
|
|
166
166
|
|
167
167
|
|
168
|
-
<span class="summary_desc"><div class='inline'>
|
169
|
-
<p>Test if all instances created so far have run to completion.</p>
|
168
|
+
<span class="summary_desc"><div class='inline'><p>Test if all instances created so far have run to completion.</p>
|
170
169
|
</div></span>
|
171
170
|
|
172
171
|
</li>
|
@@ -189,8 +188,7 @@ exception will contain the original in its <code>cause</code> field.</p>
|
|
189
188
|
|
190
189
|
|
191
190
|
|
192
|
-
<span class="summary_desc"><div class='inline'>
|
193
|
-
<p>Return the maximum number of concurrent child processes allowed.</p>
|
191
|
+
<span class="summary_desc"><div class='inline'><p>Return the maximum number of concurrent child processes allowed.</p>
|
194
192
|
</div></span>
|
195
193
|
|
196
194
|
</li>
|
@@ -213,8 +211,7 @@ exception will contain the original in its <code>cause</code> field.</p>
|
|
213
211
|
|
214
212
|
|
215
213
|
|
216
|
-
<span class="summary_desc"><div class='inline'>
|
217
|
-
<p>Set the maximum number of concurrent child processes allowed.</p>
|
214
|
+
<span class="summary_desc"><div class='inline'><p>Set the maximum number of concurrent child processes allowed.</p>
|
218
215
|
</div></span>
|
219
216
|
|
220
217
|
</li>
|
@@ -237,9 +234,7 @@ exception will contain the original in its <code>cause</code> field.</p>
|
|
237
234
|
|
238
235
|
|
239
236
|
|
240
|
-
<span class="summary_desc"><div class='inline'>
|
241
|
-
<p>Wait until all child processes have run to completion and recover their
|
242
|
-
results.</p>
|
237
|
+
<span class="summary_desc"><div class='inline'><p>Wait until all child processes have run to completion and recover their results.</p>
|
243
238
|
</div></span>
|
244
239
|
|
245
240
|
</li>
|
@@ -271,9 +266,7 @@ results.</p>
|
|
271
266
|
|
272
267
|
|
273
268
|
|
274
|
-
<span class="summary_desc"><div class='inline'>
|
275
|
-
<p>Check if the child process has finished evaluating the block and has a
|
276
|
-
result ready.</p>
|
269
|
+
<span class="summary_desc"><div class='inline'><p>Check if the child process has finished evaluating the block and has a result ready.</p>
|
277
270
|
</div></span>
|
278
271
|
|
279
272
|
</li>
|
@@ -296,8 +289,7 @@ result ready.</p>
|
|
296
289
|
|
297
290
|
|
298
291
|
|
299
|
-
<span class="summary_desc"><div class='inline'>
|
300
|
-
<p>Test if the child process has finished and its result is available.</p>
|
292
|
+
<span class="summary_desc"><div class='inline'><p>Test if the child process has finished and its result is available.</p>
|
301
293
|
</div></span>
|
302
294
|
|
303
295
|
</li>
|
@@ -322,9 +314,7 @@ result ready.</p>
|
|
322
314
|
|
323
315
|
|
324
316
|
|
325
|
-
<span class="summary_desc"><div class='inline'>
|
326
|
-
<p>In addition to creating a new <code>SimpleFuture</code>, the constructor
|
327
|
-
creates a child process and evaluates <code>action</code> in it.</p>
|
317
|
+
<span class="summary_desc"><div class='inline'><p>In addition to creating a new <code>SimpleFuture</code>, the constructor creates a child process and evaluates <code>action</code> in it.</p>
|
328
318
|
</div></span>
|
329
319
|
|
330
320
|
</li>
|
@@ -347,9 +337,7 @@ creates a child process and evaluates <code>action</code> in it.</p>
|
|
347
337
|
|
348
338
|
|
349
339
|
|
350
|
-
<span class="summary_desc"><div class='inline'>
|
351
|
-
<p>Return the result of the child process, blocking if it is not yet
|
352
|
-
available.</p>
|
340
|
+
<span class="summary_desc"><div class='inline'><p>Return the result of the child process, blocking if it is not yet available.</p>
|
353
341
|
</div></span>
|
354
342
|
|
355
343
|
</li>
|
@@ -372,9 +360,7 @@ available.</p>
|
|
372
360
|
|
373
361
|
|
374
362
|
|
375
|
-
<span class="summary_desc"><div class='inline'>
|
376
|
-
<p>Block until the child process finishes, recover its result and clean up the
|
377
|
-
process.</p>
|
363
|
+
<span class="summary_desc"><div class='inline'><p>Block until the child process finishes, recover its result and clean up the process.</p>
|
378
364
|
</div></span>
|
379
365
|
|
380
366
|
</li>
|
@@ -397,11 +383,10 @@ process.</p>
|
|
397
383
|
|
398
384
|
</h3><div class="docstring">
|
399
385
|
<div class="discussion">
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
process finishes.</p>
|
386
|
+
<p>In addition to creating a new <code>SimpleFuture</code>, the constructor
|
387
|
+
creates a child process and evaluates <code>action</code> in it. If the
|
388
|
+
maximum number of child processes would be exceeded, it will block
|
389
|
+
until a process finishes.</p>
|
405
390
|
|
406
391
|
|
407
392
|
</div>
|
@@ -462,11 +447,10 @@ process finishes.</p>
|
|
462
447
|
|
463
448
|
</h3><div class="docstring">
|
464
449
|
<div class="discussion">
|
465
|
-
|
466
|
-
|
467
|
-
effect, it will also call <code>wait</code> on instances whose child
|
450
|
+
<p>Test if all instances created so far have run to completion. As a
|
451
|
+
side effect, it will also call <code>wait</code> on instances whose child
|
468
452
|
processes are running but have finished (i.e. their
|
469
|
-
<code>check_if_ready</code> would return true.)
|
453
|
+
<code>check_if_ready</code> would return true.) This lets you use it as a
|
470
454
|
non-blocking way to clean up the remaining children.</p>
|
471
455
|
|
472
456
|
|
@@ -522,8 +506,7 @@ non-blocking way to clean up the remaining children.</p>
|
|
522
506
|
|
523
507
|
</h3><div class="docstring">
|
524
508
|
<div class="discussion">
|
525
|
-
|
526
|
-
<p>Return the maximum number of concurrent child processes allowed.</p>
|
509
|
+
<p>Return the maximum number of concurrent child processes allowed.</p>
|
527
510
|
|
528
511
|
|
529
512
|
</div>
|
@@ -559,12 +542,11 @@ non-blocking way to clean up the remaining children.</p>
|
|
559
542
|
|
560
543
|
</h3><div class="docstring">
|
561
544
|
<div class="discussion">
|
562
|
-
|
563
|
-
|
564
|
-
less than 1, it is interpreted as meaning no limit.</p>
|
545
|
+
<p>Set the maximum number of concurrent child processes allowed. If
|
546
|
+
set to less than 1, it is interpreted as meaning no limit.</p>
|
565
547
|
|
566
|
-
<p>It is initially set to the number of available cores as provided
|
567
|
-
<code>Etc</code> module.</p>
|
548
|
+
<p>It is initially set to the number of available cores as provided
|
549
|
+
by the <code>Etc</code> module.</p>
|
568
550
|
|
569
551
|
|
570
552
|
</div>
|
@@ -604,10 +586,10 @@ less than 1, it is interpreted as meaning no limit.</p>
|
|
604
586
|
|
605
587
|
</h3><div class="docstring">
|
606
588
|
<div class="discussion">
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
589
|
+
<p>Wait until all child processes have run to completion and recover
|
590
|
+
their results. Programs should call this before exiting if there
|
591
|
+
is a chance that an instance was created without having <code>wait</code>
|
592
|
+
called on it.</p>
|
611
593
|
|
612
594
|
|
613
595
|
</div>
|
@@ -657,15 +639,14 @@ an instance was created without having <code>wait</code> called on it.</p>
|
|
657
639
|
|
658
640
|
</h3><div class="docstring">
|
659
641
|
<div class="discussion">
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
<code>wait</code> will not block when called.</p>
|
642
|
+
<p>Check if the child process has finished evaluating the block and
|
643
|
+
has a result ready. If <code>check_if_ready</code> returns <code>true</code>, <code>wait</code>
|
644
|
+
will not block when called.</p>
|
664
645
|
|
665
|
-
<p>Note: <code>check_if_ready</code> tests if there's data on the pipe to
|
666
|
-
|
667
|
-
block might be able to cause a true result while still
|
668
|
-
<code>wait</code>.</p>
|
646
|
+
<p>Note: <code>check_if_ready</code> tests if there's data on the pipe to the
|
647
|
+
child process to see if it has finished. A sufficiently evil
|
648
|
+
child block might be able to cause a true result while still
|
649
|
+
blocking <code>wait</code>.</p>
|
669
650
|
|
670
651
|
<p>Don't do that.</p>
|
671
652
|
|
@@ -726,12 +707,12 @@ block might be able to cause a true result while still blocking
|
|
726
707
|
|
727
708
|
</h3><div class="docstring">
|
728
709
|
<div class="discussion">
|
729
|
-
|
730
|
-
|
710
|
+
<p>Test if the child process has finished and its result is
|
711
|
+
available.</p>
|
731
712
|
|
732
|
-
<p>Note that this will only be true after a call to <code>wait</code> (i.e.
|
733
|
-
|
734
|
-
|
713
|
+
<p>Note that this will only be true after a call to <code>wait</code> (i.e. the
|
714
|
+
child process finished <strong>and</strong> its result has been retrieved.) If
|
715
|
+
you want to see if the result is (probably) available, use
|
735
716
|
<code>check_if_ready</code>.</p>
|
736
717
|
|
737
718
|
|
@@ -781,9 +762,8 @@ retrieved.) If you want to see if the result is (probably) available, use
|
|
781
762
|
|
782
763
|
</h3><div class="docstring">
|
783
764
|
<div class="discussion">
|
784
|
-
|
785
|
-
|
786
|
-
available. Blocking is done by calling <code>wait</code>, so the process
|
765
|
+
<p>Return the result of the child process, blocking if it is not yet
|
766
|
+
available. Blocking is done by calling <code>wait</code>, so the process
|
787
767
|
will be cleaned up.</p>
|
788
768
|
|
789
769
|
|
@@ -826,15 +806,13 @@ will be cleaned up.</p>
|
|
826
806
|
|
827
807
|
</h3><div class="docstring">
|
828
808
|
<div class="discussion">
|
829
|
-
|
830
|
-
|
831
|
-
process. <code>wait</code> <strong>must</strong> be called for each
|
809
|
+
<p>Block until the child process finishes, recover its result and
|
810
|
+
clean up the process. <code>wait</code> <strong>must</strong> be called for each
|
832
811
|
<code>SimpleFuture</code> to prevent zombie processes. In practice, this is
|
833
|
-
rarely a problem since <code>value</code> calls <code>wait</code> and you
|
834
|
-
|
812
|
+
rarely a problem since <code>value</code> calls <code>wait</code> and you usually want
|
813
|
+
to get all of the values. See <code>wait_for_all</code>.</p>
|
835
814
|
|
836
|
-
<p>It is safe to call <code>wait</code> multiple times on a
|
837
|
-
<code>SimpleFuture</code>.</p>
|
815
|
+
<p>It is safe to call <code>wait</code> multiple times on a <code>SimpleFuture</code>.</p>
|
838
816
|
|
839
817
|
|
840
818
|
</div>
|
@@ -852,8 +830,7 @@ usually want to get all of the values. See <code>wait_for_all</code>.</p>
|
|
852
830
|
|
853
831
|
|
854
832
|
—
|
855
|
-
<div class='inline'>
|
856
|
-
<p>The child process raised an uncaught exception.</p>
|
833
|
+
<div class='inline'><p>The child process raised an uncaught exception.</p>
|
857
834
|
</div>
|
858
835
|
|
859
836
|
</li>
|
@@ -866,8 +843,7 @@ usually want to get all of the values. See <code>wait_for_all</code>.</p>
|
|
866
843
|
|
867
844
|
|
868
845
|
—
|
869
|
-
<div class='inline'>
|
870
|
-
<p>Marshal cannot encode the result</p>
|
846
|
+
<div class='inline'><p>Marshal cannot encode the result</p>
|
871
847
|
</div>
|
872
848
|
|
873
849
|
</li>
|
@@ -880,8 +856,7 @@ usually want to get all of the values. See <code>wait_for_all</code>.</p>
|
|
880
856
|
|
881
857
|
|
882
858
|
—
|
883
|
-
<div class='inline'>
|
884
|
-
<p>An error occurred in the IPC system or child process.</p>
|
859
|
+
<div class='inline'><p>An error occurred in the IPC system or child process.</p>
|
885
860
|
</div>
|
886
861
|
|
887
862
|
</li>
|
@@ -988,9 +963,9 @@ usually want to get all of the values. See <code>wait_for_all</code>.</p>
|
|
988
963
|
</div>
|
989
964
|
|
990
965
|
<div id="footer">
|
991
|
-
Generated on Wed Jan 17
|
966
|
+
Generated on Wed Jan 17 21:04:35 2018 by
|
992
967
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
993
|
-
0.9.12 (ruby-2.
|
968
|
+
0.9.12 (ruby-2.3.1).
|
994
969
|
</div>
|
995
970
|
|
996
971
|
</div>
|
@@ -105,9 +105,8 @@
|
|
105
105
|
|
106
106
|
<h2>Overview</h2><div class="docstring">
|
107
107
|
<div class="discussion">
|
108
|
-
|
109
|
-
|
110
|
-
child process.</p>
|
108
|
+
<p>Exception class for the case where an uncaught exception is thrown
|
109
|
+
in the child process.</p>
|
111
110
|
|
112
111
|
|
113
112
|
</div>
|
@@ -144,8 +143,7 @@ child process.</p>
|
|
144
143
|
|
145
144
|
|
146
145
|
|
147
|
-
<span class="summary_desc"><div class='inline'>
|
148
|
-
<p>If the child process threw an exception, this is it.</p>
|
146
|
+
<span class="summary_desc"><div class='inline'><p>If the child process threw an exception, this is it.</p>
|
149
147
|
</div></span>
|
150
148
|
|
151
149
|
</li>
|
@@ -183,8 +181,7 @@ child process.</p>
|
|
183
181
|
|
184
182
|
|
185
183
|
|
186
|
-
<span class="summary_desc"><div class='inline'>
|
187
|
-
<p>A new instance of ChildError.</p>
|
184
|
+
<span class="summary_desc"><div class='inline'><p>A new instance of ChildError.</p>
|
188
185
|
</div></span>
|
189
186
|
|
190
187
|
</li>
|
@@ -236,8 +233,7 @@ child process.</p>
|
|
236
233
|
|
237
234
|
</h3><div class="docstring">
|
238
235
|
<div class="discussion">
|
239
|
-
|
240
|
-
<p>Returns a new instance of ChildError</p>
|
236
|
+
<p>Returns a new instance of ChildError</p>
|
241
237
|
|
242
238
|
|
243
239
|
</div>
|
@@ -256,8 +252,7 @@ child process.</p>
|
|
256
252
|
|
257
253
|
|
258
254
|
—
|
259
|
-
<div class='inline'>
|
260
|
-
<p>The exception text.</p>
|
255
|
+
<div class='inline'><p>The exception text.</p>
|
261
256
|
</div>
|
262
257
|
|
263
258
|
</li>
|
@@ -274,8 +269,7 @@ child process.</p>
|
|
274
269
|
|
275
270
|
|
276
271
|
—
|
277
|
-
<div class='inline'>
|
278
|
-
<p>If valid, the exception raised in the child</p>
|
272
|
+
<div class='inline'><p>If valid, the exception raised in the child</p>
|
279
273
|
</div>
|
280
274
|
|
281
275
|
</li>
|
@@ -324,9 +318,8 @@ child process.</p>
|
|
324
318
|
|
325
319
|
</h3><div class="docstring">
|
326
320
|
<div class="discussion">
|
327
|
-
|
328
|
-
|
329
|
-
nil.</p>
|
321
|
+
<p>If the child process threw an exception, this is it. Otherwise,
|
322
|
+
it's nil.</p>
|
330
323
|
|
331
324
|
|
332
325
|
</div>
|
@@ -401,9 +394,9 @@ nil.</p>
|
|
401
394
|
</div>
|
402
395
|
|
403
396
|
<div id="footer">
|
404
|
-
Generated on Wed Jan 17
|
397
|
+
Generated on Wed Jan 17 21:04:35 2018 by
|
405
398
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
406
|
-
0.9.12 (ruby-2.
|
399
|
+
0.9.12 (ruby-2.3.1).
|
407
400
|
</div>
|
408
401
|
|
409
402
|
</div>
|
data/doc/SimpleFuture/Error.html
CHANGED
@@ -103,9 +103,9 @@
|
|
103
103
|
|
104
104
|
<h2>Overview</h2><div class="docstring">
|
105
105
|
<div class="discussion">
|
106
|
-
|
107
|
-
|
108
|
-
|
106
|
+
<p>Exception class for errors related to SimpleFuture. All
|
107
|
+
exceptions thrown by SimpleFuture are either <code>Error</code> or a
|
108
|
+
subclass.</p>
|
109
109
|
|
110
110
|
|
111
111
|
</div>
|
@@ -130,9 +130,9 @@ by SimpleFuture are either <code>Error</code> or a subclass.</p>
|
|
130
130
|
</div>
|
131
131
|
|
132
132
|
<div id="footer">
|
133
|
-
Generated on Wed Jan 17
|
133
|
+
Generated on Wed Jan 17 21:04:35 2018 by
|
134
134
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
135
|
-
0.9.12 (ruby-2.
|
135
|
+
0.9.12 (ruby-2.3.1).
|
136
136
|
</div>
|
137
137
|
|
138
138
|
</div>
|
@@ -105,12 +105,11 @@
|
|
105
105
|
|
106
106
|
<h2>Overview</h2><div class="docstring">
|
107
107
|
<div class="discussion">
|
108
|
-
|
109
|
-
<p>Exception class for the case(s) where the result is of a type that
|
108
|
+
<p>Exception class for the case(s) where the result is of a type that
|
110
109
|
can't be returned (e.g. because it's one of the types
|
111
|
-
<code>Marshal.dump()</code> fails on).
|
112
|
-
|
113
|
-
these instead of a <code>SimpleFuture::ChildError</code>.</p>
|
110
|
+
<code>Marshal.dump()</code> fails on). This can also apply to exceptions; if
|
111
|
+
an exception object holds an unmarshallable value, you'll get one
|
112
|
+
of these instead of a <code>SimpleFuture::ChildError</code>.</p>
|
114
113
|
|
115
114
|
|
116
115
|
</div>
|
@@ -137,9 +136,9 @@ these instead of a <code>SimpleFuture::ChildError</code>.</p>
|
|
137
136
|
</div>
|
138
137
|
|
139
138
|
<div id="footer">
|
140
|
-
Generated on Wed Jan 17
|
139
|
+
Generated on Wed Jan 17 21:04:35 2018 by
|
141
140
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
142
|
-
0.9.12 (ruby-2.
|
141
|
+
0.9.12 (ruby-2.3.1).
|
143
142
|
</div>
|
144
143
|
|
145
144
|
</div>
|
data/doc/_index.html
CHANGED
@@ -142,9 +142,9 @@
|
|
142
142
|
</div>
|
143
143
|
|
144
144
|
<div id="footer">
|
145
|
-
Generated on Wed Jan 17
|
145
|
+
Generated on Wed Jan 17 21:04:35 2018 by
|
146
146
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
147
|
-
0.9.12 (ruby-2.
|
147
|
+
0.9.12 (ruby-2.3.1).
|
148
148
|
</div>
|
149
149
|
|
150
150
|
</div>
|
data/doc/file.README.html
CHANGED
@@ -57,42 +57,37 @@
|
|
57
57
|
<div class="clear"></div>
|
58
58
|
</div>
|
59
59
|
|
60
|
-
<div id="content"><div id='filecontents'>
|
61
|
-
<h1 id="label-SimpleFuture-3A+Simple-2C+Process-based+Concurrency">SimpleFuture: Simple, Process-based Concurrency</h1>
|
60
|
+
<div id="content"><div id='filecontents'><h1>SimpleFuture: Simple, Process-based Concurrency</h1>
|
62
61
|
|
63
|
-
<p><code>SimpleFuture</code> is a Ruby module that gives you pretty good
|
64
|
-
|
65
|
-
|
66
|
-
support them.</p>
|
62
|
+
<p><code>SimpleFuture</code> is a Ruby module that gives you pretty good concurrency
|
63
|
+
without a lot of work. It doesn't use threads and so will avoid their
|
64
|
+
common pitfalls as well working on Rubies that don't support them.</p>
|
67
65
|
|
68
|
-
<p>It is a simple implementation of <a
|
69
|
-
href="https://en.wikipedia.org/wiki/Futures_and_promises">Future</a>
|
70
|
-
construct.</p>
|
66
|
+
<p>It is a simple implementation of <a href="https://en.wikipedia.org/wiki/Futures_and_promises">Future</a> construct.</p>
|
71
67
|
|
72
|
-
<h2
|
73
|
-
<ul><li>
|
74
|
-
<p><a href="https://github.com/suetanvil/simple-future/">Home Page</a></p>
|
75
|
-
</li><li>
|
76
|
-
<p><a href="https://github.com/suetanvil/simple-future/issues">Issues</a></p>
|
77
|
-
</li><li>
|
78
|
-
<p><a href="http://www.rubydoc.info/gems/simple-future">Reference Docs</a></p>
|
79
|
-
</li></ul>
|
68
|
+
<h2>Resources</h2>
|
80
69
|
|
81
|
-
<
|
70
|
+
<ul>
|
71
|
+
<li><a href="https://github.com/suetanvil/simple-future/">Home Page</a></li>
|
72
|
+
<li><a href="https://github.com/suetanvil/simple-future/issues">Issues</a></li>
|
73
|
+
<li><a href="http://www.rubydoc.info/gems/simple-future">Reference Docs</a></li>
|
74
|
+
</ul>
|
82
75
|
|
83
|
-
<
|
84
|
-
|
85
|
-
|
76
|
+
<h2>Basic idea</h2>
|
77
|
+
|
78
|
+
<p>Suppose you need to do a bunch of long-running things concurrently
|
79
|
+
(e.g. transcode a bunch of videos) and you don't want to have to deal
|
80
|
+
with threads.</p>
|
86
81
|
|
87
82
|
<p>The easy thing to do is fork a subprocess for each item and then use
|
88
83
|
<code>Marshal</code> and <code>IO.pipe</code> to retrieve the result(s).</p>
|
89
84
|
|
90
|
-
<p>That's pretty much what <code>SimpleFuture</code> does for you.
|
91
|
-
|
92
|
-
|
93
|
-
|
85
|
+
<p>That's pretty much what <code>SimpleFuture</code> does for you. You pass it a
|
86
|
+
block and it runs it in a forked child and gives you back the result
|
87
|
+
when it's ready. And as a bonus, it will limit the number of children
|
88
|
+
it creates at one time, so you don't have to.</p>
|
94
89
|
|
95
|
-
<h2
|
90
|
+
<h2>Those videos, for example</h2>
|
96
91
|
|
97
92
|
<p>So let's say you're transcoding a bunch of (legally obtained) video
|
98
93
|
files:</p>
|
@@ -104,7 +99,7 @@ files:</p>
|
|
104
99
|
</code></pre>
|
105
100
|
|
106
101
|
<p>This is nice and simple, but it isn't taking advantage of the zillions
|
107
|
-
of cores you have on your fancy modern workstation.
|
102
|
+
of cores you have on your fancy modern workstation. So you use
|
108
103
|
<code>SimpleFuture</code>:</p>
|
109
104
|
|
110
105
|
<pre class="code ruby"><code class="ruby"><span class='kw'>for</span> <span class='id identifier rubyid_vid'>vid</span> <span class='kw'>in</span> <span class='const'>Dir</span><span class='period'>.</span><span class='id identifier rubyid_glob'>glob</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>*.mp4</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span>
|
@@ -114,22 +109,21 @@ of cores you have on your fancy modern workstation. So you use
|
|
114
109
|
<span class='const'><span class='object_link'><a href="SimpleFuture.html" title="SimpleFuture (class)">SimpleFuture</a></span></span><span class='period'>.</span><span class='id identifier rubyid_wait_for_all'><span class='object_link'><a href="SimpleFuture.html#wait_for_all-class_method" title="SimpleFuture.wait_for_all (method)">wait_for_all</a></span></span>
|
115
110
|
</code></pre>
|
116
111
|
|
117
|
-
<p>And this will do what you want.
|
118
|
-
process per CPU core so you don't thrash your system.
|
119
|
-
this limit via <code>SimpleFuture.max_tasks</code>.)</p>
|
112
|
+
<p>And this will do what you want. In particular, it limits itself to
|
113
|
+
one process per CPU core so you don't thrash your system. (You can
|
114
|
+
change this limit via <code>SimpleFuture.max_tasks</code>.)</p>
|
120
115
|
|
121
|
-
<h2
|
116
|
+
<h2>Wait for it</h2>
|
122
117
|
|
123
|
-
<p>Notice that we end the script with <code>wait_for_all</code>.
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
118
|
+
<p>Notice that we end the script with <code>wait_for_all</code>. This is because
|
119
|
+
each <code>SimpleFuture</code> needs to have its <code>wait</code> method called at some
|
120
|
+
point. This is what <code>wait_for_all</code> does. (<code>SimpleFuture.new</code> will
|
121
|
+
also sometimes call an existing instance's <code>wait</code> but you can't depend
|
122
|
+
on that.)</p>
|
128
123
|
|
129
124
|
<p>Since <code>wait</code> blocks until the child process finishes, so will
|
130
|
-
<code>wait_for_all</code>.
|
131
|
-
|
132
|
-
while waiting:</p>
|
125
|
+
<code>wait_for_all</code>. If you don't like that, you can also use <code>all_done?</code>;
|
126
|
+
this won't block so you can do other stuff while waiting:</p>
|
133
127
|
|
134
128
|
<pre class="code ruby"><code class="ruby"><span class='kw'>while</span> <span class='op'>!</span><span class='const'><span class='object_link'><a href="SimpleFuture.html" title="SimpleFuture (class)">SimpleFuture</a></span></span><span class='period'>.</span><span class='id identifier rubyid_all_done?'><span class='object_link'><a href="SimpleFuture.html#all_done%3F-class_method" title="SimpleFuture.all_done? (method)">all_done?</a></span></span>
|
135
129
|
<span class='id identifier rubyid_puts'>puts</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>Waiting for child processes to finish.</span><span class='tstring_end'>"</span></span>
|
@@ -137,15 +131,15 @@ while waiting:</p>
|
|
137
131
|
<span class='kw'>end</span>
|
138
132
|
</code></pre>
|
139
133
|
|
140
|
-
<p>By the way, it's harmless to call <code>wait_for_all</code> if nothing
|
141
|
-
|
134
|
+
<p>By the way, it's harmless to call <code>wait_for_all</code> if nothing is running
|
135
|
+
so it's often good practice to just call it before quitting.</p>
|
142
136
|
|
143
|
-
<h2
|
137
|
+
<h2>I need answers</h2>
|
144
138
|
|
145
|
-
<p>But let's say that <code>transcode()</code> also returns an important
|
146
|
-
|
147
|
-
|
148
|
-
Fortunately, <code>SimpleFuture</code> handles this.</p>
|
139
|
+
<p>But let's say that <code>transcode()</code> also returns an important result such
|
140
|
+
as the compression ratio and you want to know the average. This means
|
141
|
+
that you need to get a result back from the child
|
142
|
+
process. Fortunately, <code>SimpleFuture</code> handles this.</p>
|
149
143
|
|
150
144
|
<p>First, we need to keep all of the <code>SimpleFuture</code> objects:</p>
|
151
145
|
|
@@ -167,13 +161,13 @@ Fortunately, <code>SimpleFuture</code> handles this.</p>
|
|
167
161
|
<span class='id identifier rubyid_ratios'>ratios</span><span class='period'>.</span><span class='id identifier rubyid_size'>size</span> <span class='op'>></span> <span class='int'>0</span>
|
168
162
|
</code></pre>
|
169
163
|
|
170
|
-
<p>Note that we're not calling <code>wait_for_all</code> here.
|
171
|
-
|
172
|
-
|
173
|
-
|
164
|
+
<p>Note that we're not calling <code>wait_for_all</code> here. This is because
|
165
|
+
<code>value</code> already calls <code>wait</code> and since it gets called on each
|
166
|
+
<code>SimpleFuture</code>, we know for sure that all child processes have been
|
167
|
+
cleaned up.</p>
|
174
168
|
|
175
|
-
<p>Also, it may be tempting to merge the loop and the map above but this
|
176
|
-
<strong>bad idea</strong>:</p>
|
169
|
+
<p>Also, it may be tempting to merge the loop and the map above but this
|
170
|
+
is a <strong>bad idea</strong>:</p>
|
177
171
|
|
178
172
|
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_ratios'>ratios</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='rbracket'>]</span>
|
179
173
|
<span class='kw'>for</span> <span class='id identifier rubyid_vid'>vid</span> <span class='kw'>in</span> <span class='const'>Dir</span><span class='period'>.</span><span class='id identifier rubyid_glob'>glob</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>*.mp4</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span>
|
@@ -182,71 +176,73 @@ child processes have been cleaned up.</p>
|
|
182
176
|
</span><span class='kw'>end</span>
|
183
177
|
</code></pre>
|
184
178
|
|
185
|
-
<p>Because <code>wait</code> stops until the child process finishes,
|
186
|
-
|
187
|
-
|
188
|
-
|
179
|
+
<p>Because <code>wait</code> stops until the child process finishes, you're
|
180
|
+
effectively going back to single-threaded processing. You need to
|
181
|
+
create a collection of <code>SimpleFuture</code>s first and <em>then</em> <code>wait</code> on
|
182
|
+
them.</p>
|
189
183
|
|
190
|
-
<h2
|
184
|
+
<h2>Oooopsie!</h2>
|
191
185
|
|
192
|
-
<p><code>SimpleFuture</code> tries to only throw exceptions in two cases:
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
186
|
+
<p><code>SimpleFuture</code> tries to only throw exceptions in two cases: something
|
187
|
+
is wrong with your code or something has gone wrong beyond its control
|
188
|
+
(e.g. Ruby crashed). In either case, the right thing at this point is
|
189
|
+
usually to quit. (If that's not an option, the rubydocs will give you
|
190
|
+
the gory details on what throws what.)</p>
|
197
191
|
|
198
192
|
<p>Generally, you should:</p>
|
199
|
-
|
200
|
-
<
|
201
|
-
|
202
|
-
|
203
|
-
<
|
204
|
-
breaking rule 1.</
|
205
|
-
</
|
193
|
+
|
194
|
+
<ol>
|
195
|
+
<li>Never quit the child process; always exit the block with a (simple,
|
196
|
+
Marshal-compatible) value.</li>
|
197
|
+
<li>Avoid throwing exceptions out of the child block unless it's to
|
198
|
+
avoid breaking rule 1.</li>
|
199
|
+
</ol>
|
206
200
|
|
207
201
|
<p>Also, you can probably use low-level systems methods to trick
|
208
|
-
<code>SimpleFuture</code> into doing the wrong thing.
|
202
|
+
<code>SimpleFuture</code> into doing the wrong thing. Don't do that.</p>
|
209
203
|
|
210
|
-
<h2
|
204
|
+
<h2>Installation</h2>
|
211
205
|
|
212
206
|
<p>SimpleFuture is available as a gem:</p>
|
213
207
|
|
214
|
-
<pre class="code ruby"><code class="ruby">$ [sudo] gem install simple-future
|
208
|
+
<pre class="code ruby"><code class="ruby">$ [sudo] gem install simple-future
|
209
|
+
</code></pre>
|
215
210
|
|
216
211
|
<p>Source code is available at GitHub:</p>
|
217
212
|
|
218
213
|
<pre class="code ruby"><code class="ruby">$ git clone https://github.com/suetanvil/simple-future.git
|
219
214
|
$ cd simple-future
|
220
|
-
$ rake
|
215
|
+
$ rake
|
216
|
+
</code></pre>
|
221
217
|
|
222
|
-
<p>To build, you need to install <code>rake</code>, <code>rspec</code> and
|
223
|
-
<code>yard</code>.</p>
|
218
|
+
<p>To build, you need to install <code>rake</code>, <code>rspec</code> and <code>yard</code>.</p>
|
224
219
|
|
225
|
-
<p>It should work on Ruby 2.2.0 or later, provided your Ruby/OS
|
226
|
-
supports <code>Process.fork()</code>.
|
220
|
+
<p>It should work on Ruby 2.2.0 or later, provided your Ruby/OS
|
221
|
+
combination supports <code>Process.fork()</code>. To confirm this, evaluate</p>
|
227
222
|
|
228
223
|
<pre class="code ruby"><code class="ruby"><span class='const'>Process</span><span class='period'>.</span><span class='id identifier rubyid_respond_to?'>respond_to?</span><span class='lparen'>(</span><span class='symbol'>:fork</span><span class='rparen'>)</span> <span class='comment'># true
|
229
224
|
</span></code></pre>
|
230
225
|
|
231
|
-
<p>If it returns true, you're good to go.
|
226
|
+
<p>If it returns true, you're good to go. If not, the gem will noisily
|
232
227
|
fail.</p>
|
233
228
|
|
234
|
-
<h2
|
229
|
+
<h2>Bugs and Quirks</h2>
|
235
230
|
|
236
|
-
<p><code>SimpleFuture.new</code> will block if there are too many child
|
237
|
-
|
238
|
-
|
231
|
+
<p><code>SimpleFuture.new</code> will block if there are too many child processes.
|
232
|
+
In this case, it waits for the <strong>oldest</strong> process to finish, even if
|
233
|
+
other processes have finished in the meantime.</p>
|
239
234
|
|
240
235
|
<p>The unit tests use <code>sleep</code> to give child processes a relatively
|
241
|
-
predictable execution times and test based on that.
|
242
|
-
a chance that the tests can fail on a sufficiently slow or
|
243
|
-
system.
|
236
|
+
predictable execution times and test based on that. This means
|
237
|
+
there's a chance that the tests can fail on a sufficiently slow or
|
238
|
+
overloaded system. (It's unlikely that this can happen in real life,
|
239
|
+
though.)</p>
|
244
240
|
</div></div>
|
245
241
|
|
246
242
|
<div id="footer">
|
247
|
-
Generated on Wed Jan 17
|
243
|
+
Generated on Wed Jan 17 21:04:35 2018 by
|
248
244
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
249
|
-
0.9.12 (ruby-2.
|
245
|
+
0.9.12 (ruby-2.3.1).
|
250
246
|
</div>
|
251
247
|
|
252
248
|
</div>
|
data/doc/index.html
CHANGED
@@ -57,42 +57,37 @@
|
|
57
57
|
<div class="clear"></div>
|
58
58
|
</div>
|
59
59
|
|
60
|
-
<div id="content"><div id='filecontents'>
|
61
|
-
<h1 id="label-SimpleFuture-3A+Simple-2C+Process-based+Concurrency">SimpleFuture: Simple, Process-based Concurrency</h1>
|
60
|
+
<div id="content"><div id='filecontents'><h1>SimpleFuture: Simple, Process-based Concurrency</h1>
|
62
61
|
|
63
|
-
<p><code>SimpleFuture</code> is a Ruby module that gives you pretty good
|
64
|
-
|
65
|
-
|
66
|
-
support them.</p>
|
62
|
+
<p><code>SimpleFuture</code> is a Ruby module that gives you pretty good concurrency
|
63
|
+
without a lot of work. It doesn't use threads and so will avoid their
|
64
|
+
common pitfalls as well working on Rubies that don't support them.</p>
|
67
65
|
|
68
|
-
<p>It is a simple implementation of <a
|
69
|
-
href="https://en.wikipedia.org/wiki/Futures_and_promises">Future</a>
|
70
|
-
construct.</p>
|
66
|
+
<p>It is a simple implementation of <a href="https://en.wikipedia.org/wiki/Futures_and_promises">Future</a> construct.</p>
|
71
67
|
|
72
|
-
<h2
|
73
|
-
<ul><li>
|
74
|
-
<p><a href="https://github.com/suetanvil/simple-future/">Home Page</a></p>
|
75
|
-
</li><li>
|
76
|
-
<p><a href="https://github.com/suetanvil/simple-future/issues">Issues</a></p>
|
77
|
-
</li><li>
|
78
|
-
<p><a href="http://www.rubydoc.info/gems/simple-future">Reference Docs</a></p>
|
79
|
-
</li></ul>
|
68
|
+
<h2>Resources</h2>
|
80
69
|
|
81
|
-
<
|
70
|
+
<ul>
|
71
|
+
<li><a href="https://github.com/suetanvil/simple-future/">Home Page</a></li>
|
72
|
+
<li><a href="https://github.com/suetanvil/simple-future/issues">Issues</a></li>
|
73
|
+
<li><a href="http://www.rubydoc.info/gems/simple-future">Reference Docs</a></li>
|
74
|
+
</ul>
|
82
75
|
|
83
|
-
<
|
84
|
-
|
85
|
-
|
76
|
+
<h2>Basic idea</h2>
|
77
|
+
|
78
|
+
<p>Suppose you need to do a bunch of long-running things concurrently
|
79
|
+
(e.g. transcode a bunch of videos) and you don't want to have to deal
|
80
|
+
with threads.</p>
|
86
81
|
|
87
82
|
<p>The easy thing to do is fork a subprocess for each item and then use
|
88
83
|
<code>Marshal</code> and <code>IO.pipe</code> to retrieve the result(s).</p>
|
89
84
|
|
90
|
-
<p>That's pretty much what <code>SimpleFuture</code> does for you.
|
91
|
-
|
92
|
-
|
93
|
-
|
85
|
+
<p>That's pretty much what <code>SimpleFuture</code> does for you. You pass it a
|
86
|
+
block and it runs it in a forked child and gives you back the result
|
87
|
+
when it's ready. And as a bonus, it will limit the number of children
|
88
|
+
it creates at one time, so you don't have to.</p>
|
94
89
|
|
95
|
-
<h2
|
90
|
+
<h2>Those videos, for example</h2>
|
96
91
|
|
97
92
|
<p>So let's say you're transcoding a bunch of (legally obtained) video
|
98
93
|
files:</p>
|
@@ -104,7 +99,7 @@ files:</p>
|
|
104
99
|
</code></pre>
|
105
100
|
|
106
101
|
<p>This is nice and simple, but it isn't taking advantage of the zillions
|
107
|
-
of cores you have on your fancy modern workstation.
|
102
|
+
of cores you have on your fancy modern workstation. So you use
|
108
103
|
<code>SimpleFuture</code>:</p>
|
109
104
|
|
110
105
|
<pre class="code ruby"><code class="ruby"><span class='kw'>for</span> <span class='id identifier rubyid_vid'>vid</span> <span class='kw'>in</span> <span class='const'>Dir</span><span class='period'>.</span><span class='id identifier rubyid_glob'>glob</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>*.mp4</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span>
|
@@ -114,22 +109,21 @@ of cores you have on your fancy modern workstation. So you use
|
|
114
109
|
<span class='const'><span class='object_link'><a href="SimpleFuture.html" title="SimpleFuture (class)">SimpleFuture</a></span></span><span class='period'>.</span><span class='id identifier rubyid_wait_for_all'><span class='object_link'><a href="SimpleFuture.html#wait_for_all-class_method" title="SimpleFuture.wait_for_all (method)">wait_for_all</a></span></span>
|
115
110
|
</code></pre>
|
116
111
|
|
117
|
-
<p>And this will do what you want.
|
118
|
-
process per CPU core so you don't thrash your system.
|
119
|
-
this limit via <code>SimpleFuture.max_tasks</code>.)</p>
|
112
|
+
<p>And this will do what you want. In particular, it limits itself to
|
113
|
+
one process per CPU core so you don't thrash your system. (You can
|
114
|
+
change this limit via <code>SimpleFuture.max_tasks</code>.)</p>
|
120
115
|
|
121
|
-
<h2
|
116
|
+
<h2>Wait for it</h2>
|
122
117
|
|
123
|
-
<p>Notice that we end the script with <code>wait_for_all</code>.
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
118
|
+
<p>Notice that we end the script with <code>wait_for_all</code>. This is because
|
119
|
+
each <code>SimpleFuture</code> needs to have its <code>wait</code> method called at some
|
120
|
+
point. This is what <code>wait_for_all</code> does. (<code>SimpleFuture.new</code> will
|
121
|
+
also sometimes call an existing instance's <code>wait</code> but you can't depend
|
122
|
+
on that.)</p>
|
128
123
|
|
129
124
|
<p>Since <code>wait</code> blocks until the child process finishes, so will
|
130
|
-
<code>wait_for_all</code>.
|
131
|
-
|
132
|
-
while waiting:</p>
|
125
|
+
<code>wait_for_all</code>. If you don't like that, you can also use <code>all_done?</code>;
|
126
|
+
this won't block so you can do other stuff while waiting:</p>
|
133
127
|
|
134
128
|
<pre class="code ruby"><code class="ruby"><span class='kw'>while</span> <span class='op'>!</span><span class='const'><span class='object_link'><a href="SimpleFuture.html" title="SimpleFuture (class)">SimpleFuture</a></span></span><span class='period'>.</span><span class='id identifier rubyid_all_done?'><span class='object_link'><a href="SimpleFuture.html#all_done%3F-class_method" title="SimpleFuture.all_done? (method)">all_done?</a></span></span>
|
135
129
|
<span class='id identifier rubyid_puts'>puts</span> <span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>Waiting for child processes to finish.</span><span class='tstring_end'>"</span></span>
|
@@ -137,15 +131,15 @@ while waiting:</p>
|
|
137
131
|
<span class='kw'>end</span>
|
138
132
|
</code></pre>
|
139
133
|
|
140
|
-
<p>By the way, it's harmless to call <code>wait_for_all</code> if nothing
|
141
|
-
|
134
|
+
<p>By the way, it's harmless to call <code>wait_for_all</code> if nothing is running
|
135
|
+
so it's often good practice to just call it before quitting.</p>
|
142
136
|
|
143
|
-
<h2
|
137
|
+
<h2>I need answers</h2>
|
144
138
|
|
145
|
-
<p>But let's say that <code>transcode()</code> also returns an important
|
146
|
-
|
147
|
-
|
148
|
-
Fortunately, <code>SimpleFuture</code> handles this.</p>
|
139
|
+
<p>But let's say that <code>transcode()</code> also returns an important result such
|
140
|
+
as the compression ratio and you want to know the average. This means
|
141
|
+
that you need to get a result back from the child
|
142
|
+
process. Fortunately, <code>SimpleFuture</code> handles this.</p>
|
149
143
|
|
150
144
|
<p>First, we need to keep all of the <code>SimpleFuture</code> objects:</p>
|
151
145
|
|
@@ -167,13 +161,13 @@ Fortunately, <code>SimpleFuture</code> handles this.</p>
|
|
167
161
|
<span class='id identifier rubyid_ratios'>ratios</span><span class='period'>.</span><span class='id identifier rubyid_size'>size</span> <span class='op'>></span> <span class='int'>0</span>
|
168
162
|
</code></pre>
|
169
163
|
|
170
|
-
<p>Note that we're not calling <code>wait_for_all</code> here.
|
171
|
-
|
172
|
-
|
173
|
-
|
164
|
+
<p>Note that we're not calling <code>wait_for_all</code> here. This is because
|
165
|
+
<code>value</code> already calls <code>wait</code> and since it gets called on each
|
166
|
+
<code>SimpleFuture</code>, we know for sure that all child processes have been
|
167
|
+
cleaned up.</p>
|
174
168
|
|
175
|
-
<p>Also, it may be tempting to merge the loop and the map above but this
|
176
|
-
<strong>bad idea</strong>:</p>
|
169
|
+
<p>Also, it may be tempting to merge the loop and the map above but this
|
170
|
+
is a <strong>bad idea</strong>:</p>
|
177
171
|
|
178
172
|
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_ratios'>ratios</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='rbracket'>]</span>
|
179
173
|
<span class='kw'>for</span> <span class='id identifier rubyid_vid'>vid</span> <span class='kw'>in</span> <span class='const'>Dir</span><span class='period'>.</span><span class='id identifier rubyid_glob'>glob</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>*.mp4</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span>
|
@@ -182,71 +176,73 @@ child processes have been cleaned up.</p>
|
|
182
176
|
</span><span class='kw'>end</span>
|
183
177
|
</code></pre>
|
184
178
|
|
185
|
-
<p>Because <code>wait</code> stops until the child process finishes,
|
186
|
-
|
187
|
-
|
188
|
-
|
179
|
+
<p>Because <code>wait</code> stops until the child process finishes, you're
|
180
|
+
effectively going back to single-threaded processing. You need to
|
181
|
+
create a collection of <code>SimpleFuture</code>s first and <em>then</em> <code>wait</code> on
|
182
|
+
them.</p>
|
189
183
|
|
190
|
-
<h2
|
184
|
+
<h2>Oooopsie!</h2>
|
191
185
|
|
192
|
-
<p><code>SimpleFuture</code> tries to only throw exceptions in two cases:
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
186
|
+
<p><code>SimpleFuture</code> tries to only throw exceptions in two cases: something
|
187
|
+
is wrong with your code or something has gone wrong beyond its control
|
188
|
+
(e.g. Ruby crashed). In either case, the right thing at this point is
|
189
|
+
usually to quit. (If that's not an option, the rubydocs will give you
|
190
|
+
the gory details on what throws what.)</p>
|
197
191
|
|
198
192
|
<p>Generally, you should:</p>
|
199
|
-
|
200
|
-
<
|
201
|
-
|
202
|
-
|
203
|
-
<
|
204
|
-
breaking rule 1.</
|
205
|
-
</
|
193
|
+
|
194
|
+
<ol>
|
195
|
+
<li>Never quit the child process; always exit the block with a (simple,
|
196
|
+
Marshal-compatible) value.</li>
|
197
|
+
<li>Avoid throwing exceptions out of the child block unless it's to
|
198
|
+
avoid breaking rule 1.</li>
|
199
|
+
</ol>
|
206
200
|
|
207
201
|
<p>Also, you can probably use low-level systems methods to trick
|
208
|
-
<code>SimpleFuture</code> into doing the wrong thing.
|
202
|
+
<code>SimpleFuture</code> into doing the wrong thing. Don't do that.</p>
|
209
203
|
|
210
|
-
<h2
|
204
|
+
<h2>Installation</h2>
|
211
205
|
|
212
206
|
<p>SimpleFuture is available as a gem:</p>
|
213
207
|
|
214
|
-
<pre class="code ruby"><code class="ruby">$ [sudo] gem install simple-future
|
208
|
+
<pre class="code ruby"><code class="ruby">$ [sudo] gem install simple-future
|
209
|
+
</code></pre>
|
215
210
|
|
216
211
|
<p>Source code is available at GitHub:</p>
|
217
212
|
|
218
213
|
<pre class="code ruby"><code class="ruby">$ git clone https://github.com/suetanvil/simple-future.git
|
219
214
|
$ cd simple-future
|
220
|
-
$ rake
|
215
|
+
$ rake
|
216
|
+
</code></pre>
|
221
217
|
|
222
|
-
<p>To build, you need to install <code>rake</code>, <code>rspec</code> and
|
223
|
-
<code>yard</code>.</p>
|
218
|
+
<p>To build, you need to install <code>rake</code>, <code>rspec</code> and <code>yard</code>.</p>
|
224
219
|
|
225
|
-
<p>It should work on Ruby 2.2.0 or later, provided your Ruby/OS
|
226
|
-
supports <code>Process.fork()</code>.
|
220
|
+
<p>It should work on Ruby 2.2.0 or later, provided your Ruby/OS
|
221
|
+
combination supports <code>Process.fork()</code>. To confirm this, evaluate</p>
|
227
222
|
|
228
223
|
<pre class="code ruby"><code class="ruby"><span class='const'>Process</span><span class='period'>.</span><span class='id identifier rubyid_respond_to?'>respond_to?</span><span class='lparen'>(</span><span class='symbol'>:fork</span><span class='rparen'>)</span> <span class='comment'># true
|
229
224
|
</span></code></pre>
|
230
225
|
|
231
|
-
<p>If it returns true, you're good to go.
|
226
|
+
<p>If it returns true, you're good to go. If not, the gem will noisily
|
232
227
|
fail.</p>
|
233
228
|
|
234
|
-
<h2
|
229
|
+
<h2>Bugs and Quirks</h2>
|
235
230
|
|
236
|
-
<p><code>SimpleFuture.new</code> will block if there are too many child
|
237
|
-
|
238
|
-
|
231
|
+
<p><code>SimpleFuture.new</code> will block if there are too many child processes.
|
232
|
+
In this case, it waits for the <strong>oldest</strong> process to finish, even if
|
233
|
+
other processes have finished in the meantime.</p>
|
239
234
|
|
240
235
|
<p>The unit tests use <code>sleep</code> to give child processes a relatively
|
241
|
-
predictable execution times and test based on that.
|
242
|
-
a chance that the tests can fail on a sufficiently slow or
|
243
|
-
system.
|
236
|
+
predictable execution times and test based on that. This means
|
237
|
+
there's a chance that the tests can fail on a sufficiently slow or
|
238
|
+
overloaded system. (It's unlikely that this can happen in real life,
|
239
|
+
though.)</p>
|
244
240
|
</div></div>
|
245
241
|
|
246
242
|
<div id="footer">
|
247
|
-
Generated on Wed Jan 17
|
243
|
+
Generated on Wed Jan 17 21:04:35 2018 by
|
248
244
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
249
|
-
0.9.12 (ruby-2.
|
245
|
+
0.9.12 (ruby-2.3.1).
|
250
246
|
</div>
|
251
247
|
|
252
248
|
</div>
|
@@ -100,9 +100,9 @@
|
|
100
100
|
</div>
|
101
101
|
|
102
102
|
<div id="footer">
|
103
|
-
Generated on Wed Jan 17
|
103
|
+
Generated on Wed Jan 17 21:04:35 2018 by
|
104
104
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
105
|
-
0.9.12 (ruby-2.
|
105
|
+
0.9.12 (ruby-2.3.1).
|
106
106
|
</div>
|
107
107
|
|
108
108
|
</div>
|
data/simple-future.gemspec
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
|
2
2
|
Gem::Specification.new do |s|
|
3
3
|
s.name = 'simple-future'
|
4
|
-
s.version = '1.0.0
|
5
|
-
s.date = '2018-01-
|
4
|
+
s.version = '1.0.0'
|
5
|
+
s.date = '2018-01-17'
|
6
6
|
s.summary = "A Future class for simple process-based concurrency."
|
7
7
|
s.description = <<-EOF
|
8
8
|
SimpleFuture is class that simplifies coarse-grained concurrency using
|
@@ -15,8 +15,11 @@ Gem::Specification.new do |s|
|
|
15
15
|
EOF
|
16
16
|
s.authors = ["Chris Reuter"]
|
17
17
|
s.email = 'chris@blit.ca'
|
18
|
+
|
19
|
+
# I'm just going to add everything so that if you've got the gem,
|
20
|
+
# you've also got the source distribution. Yay! Open source!
|
18
21
|
s.files = ["README.md", "LICENSE.txt", "simple-future.gemspec",
|
19
|
-
"Rakefile"] +
|
22
|
+
"Rakefile", ".yardopts"] +
|
20
23
|
Dir.glob('doc/**/*') +
|
21
24
|
Dir.glob('{spec,lib}/*.rb')
|
22
25
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple-future
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Reuter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -63,6 +63,7 @@ executables: []
|
|
63
63
|
extensions: []
|
64
64
|
extra_rdoc_files: []
|
65
65
|
files:
|
66
|
+
- ".yardopts"
|
66
67
|
- LICENSE.txt
|
67
68
|
- README.md
|
68
69
|
- Rakefile
|
@@ -103,13 +104,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
103
104
|
version: 2.2.0
|
104
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
106
|
requirements:
|
106
|
-
- - "
|
107
|
+
- - ">="
|
107
108
|
- !ruby/object:Gem::Version
|
108
|
-
version:
|
109
|
+
version: '0'
|
109
110
|
requirements:
|
110
111
|
- A version of Ruby that implements Process.fork
|
111
112
|
rubyforge_project:
|
112
|
-
rubygems_version: 2.
|
113
|
+
rubygems_version: 2.5.1
|
113
114
|
signing_key:
|
114
115
|
specification_version: 4
|
115
116
|
summary: A Future class for simple process-based concurrency.
|