concurrent-ruby 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +478 -0
- data/Gemfile +41 -0
- data/LICENSE.md +23 -0
- data/README.md +381 -0
- data/Rakefile +327 -0
- data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +159 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +307 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
- data/lib/concurrent-ruby.rb +1 -0
- data/lib/concurrent.rb +134 -0
- data/lib/concurrent/agent.rb +587 -0
- data/lib/concurrent/array.rb +66 -0
- data/lib/concurrent/async.rb +459 -0
- data/lib/concurrent/atom.rb +222 -0
- data/lib/concurrent/atomic/abstract_thread_local_var.rb +66 -0
- data/lib/concurrent/atomic/atomic_boolean.rb +126 -0
- data/lib/concurrent/atomic/atomic_fixnum.rb +143 -0
- data/lib/concurrent/atomic/atomic_markable_reference.rb +164 -0
- data/lib/concurrent/atomic/atomic_reference.rb +204 -0
- data/lib/concurrent/atomic/count_down_latch.rb +100 -0
- data/lib/concurrent/atomic/cyclic_barrier.rb +128 -0
- data/lib/concurrent/atomic/event.rb +109 -0
- data/lib/concurrent/atomic/java_count_down_latch.rb +42 -0
- data/lib/concurrent/atomic/java_thread_local_var.rb +37 -0
- data/lib/concurrent/atomic/mutex_atomic_boolean.rb +62 -0
- data/lib/concurrent/atomic/mutex_atomic_fixnum.rb +75 -0
- data/lib/concurrent/atomic/mutex_count_down_latch.rb +44 -0
- data/lib/concurrent/atomic/mutex_semaphore.rb +115 -0
- data/lib/concurrent/atomic/read_write_lock.rb +254 -0
- data/lib/concurrent/atomic/reentrant_read_write_lock.rb +379 -0
- data/lib/concurrent/atomic/ruby_thread_local_var.rb +161 -0
- data/lib/concurrent/atomic/semaphore.rb +145 -0
- data/lib/concurrent/atomic/thread_local_var.rb +104 -0
- data/lib/concurrent/atomic_reference/mutex_atomic.rb +56 -0
- data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +28 -0
- data/lib/concurrent/atomics.rb +10 -0
- data/lib/concurrent/collection/copy_on_notify_observer_set.rb +107 -0
- data/lib/concurrent/collection/copy_on_write_observer_set.rb +111 -0
- data/lib/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
- data/lib/concurrent/collection/lock_free_stack.rb +158 -0
- data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
- data/lib/concurrent/collection/map/mri_map_backend.rb +66 -0
- data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +140 -0
- data/lib/concurrent/collection/map/synchronized_map_backend.rb +82 -0
- data/lib/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
- data/lib/concurrent/collection/ruby_non_concurrent_priority_queue.rb +150 -0
- data/lib/concurrent/concern/deprecation.rb +34 -0
- data/lib/concurrent/concern/dereferenceable.rb +73 -0
- data/lib/concurrent/concern/logging.rb +32 -0
- data/lib/concurrent/concern/obligation.rb +220 -0
- data/lib/concurrent/concern/observable.rb +110 -0
- data/lib/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent/configuration.rb +184 -0
- data/lib/concurrent/constants.rb +8 -0
- data/lib/concurrent/dataflow.rb +81 -0
- data/lib/concurrent/delay.rb +199 -0
- data/lib/concurrent/errors.rb +69 -0
- data/lib/concurrent/exchanger.rb +352 -0
- data/lib/concurrent/executor/abstract_executor_service.rb +134 -0
- data/lib/concurrent/executor/cached_thread_pool.rb +62 -0
- data/lib/concurrent/executor/executor_service.rb +185 -0
- data/lib/concurrent/executor/fixed_thread_pool.rb +206 -0
- data/lib/concurrent/executor/immediate_executor.rb +66 -0
- data/lib/concurrent/executor/indirect_immediate_executor.rb +44 -0
- data/lib/concurrent/executor/java_executor_service.rb +91 -0
- data/lib/concurrent/executor/java_single_thread_executor.rb +29 -0
- data/lib/concurrent/executor/java_thread_pool_executor.rb +123 -0
- data/lib/concurrent/executor/ruby_executor_service.rb +78 -0
- data/lib/concurrent/executor/ruby_single_thread_executor.rb +22 -0
- data/lib/concurrent/executor/ruby_thread_pool_executor.rb +362 -0
- data/lib/concurrent/executor/safe_task_executor.rb +35 -0
- data/lib/concurrent/executor/serial_executor_service.rb +34 -0
- data/lib/concurrent/executor/serialized_execution.rb +107 -0
- data/lib/concurrent/executor/serialized_execution_delegator.rb +28 -0
- data/lib/concurrent/executor/simple_executor_service.rb +100 -0
- data/lib/concurrent/executor/single_thread_executor.rb +56 -0
- data/lib/concurrent/executor/thread_pool_executor.rb +87 -0
- data/lib/concurrent/executor/timer_set.rb +173 -0
- data/lib/concurrent/executors.rb +20 -0
- data/lib/concurrent/future.rb +141 -0
- data/lib/concurrent/hash.rb +59 -0
- data/lib/concurrent/immutable_struct.rb +93 -0
- data/lib/concurrent/ivar.rb +207 -0
- data/lib/concurrent/map.rb +337 -0
- data/lib/concurrent/maybe.rb +229 -0
- data/lib/concurrent/mutable_struct.rb +229 -0
- data/lib/concurrent/mvar.rb +242 -0
- data/lib/concurrent/options.rb +42 -0
- data/lib/concurrent/promise.rb +579 -0
- data/lib/concurrent/promises.rb +2167 -0
- data/lib/concurrent/re_include.rb +58 -0
- data/lib/concurrent/scheduled_task.rb +318 -0
- data/lib/concurrent/set.rb +66 -0
- data/lib/concurrent/settable_struct.rb +129 -0
- data/lib/concurrent/synchronization.rb +30 -0
- data/lib/concurrent/synchronization/abstract_lockable_object.rb +98 -0
- data/lib/concurrent/synchronization/abstract_object.rb +24 -0
- data/lib/concurrent/synchronization/abstract_struct.rb +160 -0
- data/lib/concurrent/synchronization/condition.rb +60 -0
- data/lib/concurrent/synchronization/jruby_lockable_object.rb +13 -0
- data/lib/concurrent/synchronization/jruby_object.rb +45 -0
- data/lib/concurrent/synchronization/lock.rb +36 -0
- data/lib/concurrent/synchronization/lockable_object.rb +74 -0
- data/lib/concurrent/synchronization/mri_object.rb +44 -0
- data/lib/concurrent/synchronization/mutex_lockable_object.rb +76 -0
- data/lib/concurrent/synchronization/object.rb +183 -0
- data/lib/concurrent/synchronization/rbx_lockable_object.rb +65 -0
- data/lib/concurrent/synchronization/rbx_object.rb +49 -0
- data/lib/concurrent/synchronization/truffleruby_object.rb +47 -0
- data/lib/concurrent/synchronization/volatile.rb +36 -0
- data/lib/concurrent/thread_safe/synchronized_delegator.rb +50 -0
- data/lib/concurrent/thread_safe/util.rb +16 -0
- data/lib/concurrent/thread_safe/util/adder.rb +74 -0
- data/lib/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
- data/lib/concurrent/thread_safe/util/data_structures.rb +63 -0
- data/lib/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
- data/lib/concurrent/thread_safe/util/striped64.rb +246 -0
- data/lib/concurrent/thread_safe/util/volatile.rb +75 -0
- data/lib/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
- data/lib/concurrent/timer_task.rb +334 -0
- data/lib/concurrent/tuple.rb +86 -0
- data/lib/concurrent/tvar.rb +258 -0
- data/lib/concurrent/utility/at_exit.rb +97 -0
- data/lib/concurrent/utility/engine.rb +56 -0
- data/lib/concurrent/utility/monotonic_time.rb +58 -0
- data/lib/concurrent/utility/native_extension_loader.rb +79 -0
- data/lib/concurrent/utility/native_integer.rb +53 -0
- data/lib/concurrent/utility/processor_counter.rb +158 -0
- data/lib/concurrent/version.rb +3 -0
- metadata +193 -0
data/Gemfile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'lib/concurrent/version')
|
4
|
+
require File.join(File.dirname(__FILE__ ), 'lib-edge/concurrent/edge/version')
|
5
|
+
|
6
|
+
no_path = ENV['NO_PATH']
|
7
|
+
options = no_path ? {} : { path: '.' }
|
8
|
+
|
9
|
+
gem 'concurrent-ruby', Concurrent::VERSION, options
|
10
|
+
gem 'concurrent-ruby-edge', Concurrent::EDGE_VERSION, options
|
11
|
+
gem 'concurrent-ruby-ext', Concurrent::VERSION, options.merge(platform: :mri)
|
12
|
+
|
13
|
+
group :development do
|
14
|
+
gem 'rake', '~> 12.0'
|
15
|
+
gem 'rake-compiler', '~> 1.0', '>= 1.0.7'
|
16
|
+
gem 'rake-compiler-dock', '~> 0.7.0'
|
17
|
+
gem 'pry', '~> 0.11', platforms: :mri
|
18
|
+
end
|
19
|
+
|
20
|
+
group :documentation, optional: true do
|
21
|
+
gem 'yard', '~> 0.9.0', require: false
|
22
|
+
gem 'redcarpet', '~> 3.0', platforms: :mri # understands github markdown
|
23
|
+
gem 'md-ruby-eval', '~> 0.6'
|
24
|
+
end
|
25
|
+
|
26
|
+
group :testing do
|
27
|
+
gem 'rspec', '~> 3.7'
|
28
|
+
gem 'timecop', '~> 0.7.4'
|
29
|
+
gem 'sigdump', require: false
|
30
|
+
end
|
31
|
+
|
32
|
+
# made opt-in since it will not install on jruby 1.7
|
33
|
+
group :coverage, optional: !ENV['COVERAGE'] do
|
34
|
+
gem 'simplecov', '~> 0.16.0', require: false
|
35
|
+
gem 'coveralls', '~> 0.8.2', require: false
|
36
|
+
end
|
37
|
+
|
38
|
+
group :benchmarks, optional: true do
|
39
|
+
gem 'benchmark-ips', '~> 2.7'
|
40
|
+
gem 'bench9000'
|
41
|
+
end
|
data/LICENSE.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
```
|
2
|
+
Copyright (c) Jerry D'Antonio -- released under the MIT license.
|
3
|
+
|
4
|
+
http://www.opensource.org/licenses/mit-license.php
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
8
|
+
in the Software without restriction, including without limitation the rights
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
11
|
+
furnished to do so, subject to the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in
|
14
|
+
all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
THE SOFTWARE.
|
23
|
+
```
|
data/README.md
ADDED
@@ -0,0 +1,381 @@
|
|
1
|
+
# Concurrent Ruby
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/concurrent-ruby.svg)](http://badge.fury.io/rb/concurrent-ruby)
|
4
|
+
[![Build Status](https://travis-ci.org/ruby-concurrency/concurrent-ruby.svg?branch=master)](https://travis-ci.org/ruby-concurrency/concurrent-ruby)
|
5
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/iq8aboyuu3etad4w?svg=true)](https://ci.appveyor.com/project/rubyconcurrency/concurrent-ruby)
|
6
|
+
[![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT)
|
7
|
+
[![Gitter chat](https://img.shields.io/badge/IRC%20(gitter)-devs%20%26%20users-brightgreen.svg)](https://gitter.im/ruby-concurrency/concurrent-ruby)
|
8
|
+
|
9
|
+
Modern concurrency tools for Ruby. Inspired by
|
10
|
+
[Erlang](http://www.erlang.org/doc/reference_manual/processes.html),
|
11
|
+
[Clojure](http://clojure.org/concurrent_programming),
|
12
|
+
[Scala](http://akka.io/),
|
13
|
+
[Haskell](http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell),
|
14
|
+
[F#](http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx),
|
15
|
+
[C#](http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx),
|
16
|
+
[Java](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html),
|
17
|
+
and classic concurrency patterns.
|
18
|
+
|
19
|
+
<img src="https://raw.githubusercontent.com/ruby-concurrency/concurrent-ruby/master/docs-source/logo/concurrent-ruby-logo-300x300.png" align="right" style="margin-left: 20px;" />
|
20
|
+
|
21
|
+
The design goals of this gem are:
|
22
|
+
|
23
|
+
* Be an 'unopinionated' toolbox that provides useful utilities without debating which is better
|
24
|
+
or why
|
25
|
+
* Remain free of external gem dependencies
|
26
|
+
* Stay true to the spirit of the languages providing inspiration
|
27
|
+
* But implement in a way that makes sense for Ruby
|
28
|
+
* Keep the semantics as idiomatic Ruby as possible
|
29
|
+
* Support features that make sense in Ruby
|
30
|
+
* Exclude features that don't make sense in Ruby
|
31
|
+
* Be small, lean, and loosely coupled
|
32
|
+
* Thread-safety
|
33
|
+
* Backward compatibility
|
34
|
+
|
35
|
+
## Contributing
|
36
|
+
|
37
|
+
**This gem depends on
|
38
|
+
[contributions](https://github.com/ruby-concurrency/concurrent-ruby/graphs/contributors) and we
|
39
|
+
appreciate your help. Would you like to contribute? Great! Have a look at
|
40
|
+
[issues with `looking-for-contributor` label](https://github.com/ruby-concurrency/concurrent-ruby/issues?q=is%3Aissue+is%3Aopen+label%3Alooking-for-contributor).** And if you pick something up let us know on the issue.
|
41
|
+
|
42
|
+
## Thread Safety
|
43
|
+
|
44
|
+
*Concurrent Ruby makes one of the strongest thread safety guarantees of any Ruby concurrency
|
45
|
+
library, providing consistent behavior and guarantees on all four of the main Ruby interpreters
|
46
|
+
(MRI/CRuby, JRuby, Rubinius, TruffleRuby).*
|
47
|
+
|
48
|
+
Every abstraction in this library is thread safe. Specific thread safety guarantees are documented
|
49
|
+
with each abstraction.
|
50
|
+
|
51
|
+
It is critical to remember, however, that Ruby is a language of mutable references. *No*
|
52
|
+
concurrency library for Ruby can ever prevent the user from making thread safety mistakes (such as
|
53
|
+
sharing a mutable object between threads and modifying it on both threads) or from creating
|
54
|
+
deadlocks through incorrect use of locks. All the library can do is provide safe abstractions which
|
55
|
+
encourage safe practices. Concurrent Ruby provides more safe concurrency abstractions than any
|
56
|
+
other Ruby library, many of which support the mantra of
|
57
|
+
["Do not communicate by sharing memory; instead, share memory by communicating"](https://blog.golang.org/share-memory-by-communicating).
|
58
|
+
Concurrent Ruby is also the only Ruby library which provides a full suite of thread safe and
|
59
|
+
immutable variable types and data structures.
|
60
|
+
|
61
|
+
We've also initiated discussion to document [memory model](docs-source/synchronization.md) of Ruby which
|
62
|
+
would provide consistent behaviour and guarantees on all four of the main Ruby interpreters
|
63
|
+
(MRI/CRuby, JRuby, Rubinius, TruffleRuby).
|
64
|
+
|
65
|
+
## Features & Documentation
|
66
|
+
|
67
|
+
**The primary site for documentation is the automatically generated
|
68
|
+
[API documentation](http://ruby-concurrency.github.io/concurrent-ruby/index.html) which is up to
|
69
|
+
date with latest release.** This readme matches the master so may contain new stuff not yet
|
70
|
+
released.
|
71
|
+
|
72
|
+
We also have a [IRC (gitter)](https://gitter.im/ruby-concurrency/concurrent-ruby).
|
73
|
+
|
74
|
+
### Versioning
|
75
|
+
|
76
|
+
* `concurrent-ruby` uses [Semantic Versioning](http://semver.org/)
|
77
|
+
* `concurrent-ruby-ext` has always same version as `concurrent-ruby`
|
78
|
+
* `concurrent-ruby-edge` will always be 0.y.z therefore following
|
79
|
+
[point 4](http://semver.org/#spec-item-4) applies *"Major version zero
|
80
|
+
(0.y.z) is for initial development. Anything may change at any time. The
|
81
|
+
public API should not be considered stable."* However we additionally use
|
82
|
+
following rules:
|
83
|
+
* Minor version increment means incompatible changes were made
|
84
|
+
* Patch version increment means only compatible changes were made
|
85
|
+
|
86
|
+
|
87
|
+
#### General-purpose Concurrency Abstractions
|
88
|
+
|
89
|
+
* [Async](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Async.html):
|
90
|
+
A mixin module that provides simple asynchronous behavior to a class. Loosely based on Erlang's
|
91
|
+
[gen_server](http://www.erlang.org/doc/man/gen_server.html).
|
92
|
+
* [ScheduledTask](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ScheduledTask.html):
|
93
|
+
Like a Future scheduled for a specific future time.
|
94
|
+
* [TimerTask](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/TimerTask.html):
|
95
|
+
A Thread that periodically wakes up to perform work at regular intervals.
|
96
|
+
* [Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html):
|
97
|
+
Unified implementation of futures and promises which combines features of previous `Future`,
|
98
|
+
`Promise`, `IVar`, `Event`, `dataflow`, `Delay`, and (partially) `TimerTask` into a single
|
99
|
+
framework. It extensively uses the new synchronization layer to make all the features
|
100
|
+
**non-blocking** and **lock-free**, with the exception of obviously blocking operations like
|
101
|
+
`#wait`, `#value`. It also offers better performance.
|
102
|
+
|
103
|
+
#### Thread-safe Value Objects, Structures, and Collections
|
104
|
+
|
105
|
+
Collection classes that were originally part of the (deprecated) `thread_safe` gem:
|
106
|
+
|
107
|
+
* [Array](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Array.html) A thread-safe
|
108
|
+
subclass of Ruby's standard [Array](http://ruby-doc.org/core-2.2.0/Array.html).
|
109
|
+
* [Hash](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Hash.html) A thread-safe
|
110
|
+
subclass of Ruby's standard [Hash](http://ruby-doc.org/core-2.2.0/Hash.html).
|
111
|
+
* [Set](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Set.html) A thread-safe
|
112
|
+
subclass of Ruby's standard [Set](http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html).
|
113
|
+
* [Map](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Map.html) A hash-like object
|
114
|
+
that should have much better performance characteristics, especially under high concurrency,
|
115
|
+
than `Concurrent::Hash`.
|
116
|
+
* [Tuple](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Tuple.html) A fixed size
|
117
|
+
array with volatile (synchronized, thread safe) getters/setters.
|
118
|
+
|
119
|
+
Value objects inspired by other languages:
|
120
|
+
|
121
|
+
* [Maybe](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Maybe.html) A thread-safe,
|
122
|
+
immutable object representing an optional value, based on
|
123
|
+
[Haskell Data.Maybe](https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html).
|
124
|
+
|
125
|
+
Structure classes derived from Ruby's [Struct](http://ruby-doc.org/core-2.2.0/Struct.html):
|
126
|
+
|
127
|
+
* [ImmutableStruct](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ImmutableStruct.html)
|
128
|
+
Immutable struct where values are set at construction and cannot be changed later.
|
129
|
+
* [MutableStruct](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/MutableStruct.html)
|
130
|
+
Synchronized, mutable struct where values can be safely changed at any time.
|
131
|
+
* [SettableStruct](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/SettableStruct.html)
|
132
|
+
Synchronized, write-once struct where values can be set at most once, either at construction
|
133
|
+
or any time thereafter.
|
134
|
+
|
135
|
+
Thread-safe variables:
|
136
|
+
|
137
|
+
* [Agent](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Agent.html): A way to
|
138
|
+
manage shared, mutable, *asynchronous*, independent state. Based on Clojure's
|
139
|
+
[Agent](http://clojure.org/agents).
|
140
|
+
* [Atom](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Atom.html): A way to manage
|
141
|
+
shared, mutable, *synchronous*, independent state. Based on Clojure's
|
142
|
+
[Atom](http://clojure.org/atoms).
|
143
|
+
* [AtomicBoolean](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/AtomicBoolean.html)
|
144
|
+
A boolean value that can be updated atomically.
|
145
|
+
* [AtomicFixnum](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/AtomicFixnum.html)
|
146
|
+
A numeric value that can be updated atomically.
|
147
|
+
* [AtomicReference](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/AtomicReference.html)
|
148
|
+
An object reference that may be updated atomically.
|
149
|
+
* [Exchanger](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Exchanger.html)
|
150
|
+
A synchronization point at which threads can pair and swap elements within pairs. Based on
|
151
|
+
Java's [Exchanger](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html).
|
152
|
+
* [MVar](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/MVar.html) A synchronized
|
153
|
+
single element container. Based on Haskell's
|
154
|
+
[MVar](https://hackage.haskell.org/package/base-4.8.1.0/docs/Control-Concurrent-MVar.html) and
|
155
|
+
Scala's [MVar](http://docs.typelevel.org/api/scalaz/nightly/index.html#scalaz.concurrent.MVar$).
|
156
|
+
* [ThreadLocalVar](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ThreadLocalVar.html)
|
157
|
+
A variable where the value is different for each thread.
|
158
|
+
* [TVar](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/TVar.html) A transactional
|
159
|
+
variable implementing software transactional memory (STM). Based on Clojure's
|
160
|
+
[Ref](http://clojure.org/refs).
|
161
|
+
|
162
|
+
#### Java-inspired ThreadPools and Other Executors
|
163
|
+
|
164
|
+
* See the [thread pool](http://ruby-concurrency.github.io/concurrent-ruby/master/file.thread_pools.html)
|
165
|
+
overview, which also contains a list of other Executors available.
|
166
|
+
|
167
|
+
#### Thread Synchronization Classes and Algorithms
|
168
|
+
|
169
|
+
* [CountDownLatch](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/CountDownLatch.html)
|
170
|
+
A synchronization object that allows one thread to wait on multiple other threads.
|
171
|
+
* [CyclicBarrier](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/CyclicBarrier.html)
|
172
|
+
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
|
173
|
+
* [Event](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Event.html) Old school
|
174
|
+
kernel-style event.
|
175
|
+
* [ReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ReadWriteLock.html)
|
176
|
+
A lock that supports multiple readers but only one writer.
|
177
|
+
* [ReentrantReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ReentrantReadWriteLock.html)
|
178
|
+
A read/write lock with reentrant and upgrade features.
|
179
|
+
* [Semaphore](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Semaphore.html)
|
180
|
+
A counting-based locking mechanism that uses permits.
|
181
|
+
* [AtomicMarkableReference](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/AtomicMarkableReference.html)
|
182
|
+
|
183
|
+
#### Deprecated
|
184
|
+
|
185
|
+
Deprecated features are still available and bugs are being fixed, but new features will not be added.
|
186
|
+
|
187
|
+
* ~~[Future](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Future.html):
|
188
|
+
An asynchronous operation that produces a value.~~ Replaced by
|
189
|
+
[Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html).
|
190
|
+
* ~~[.dataflow](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent.html#dataflow-class_method):
|
191
|
+
Built on Futures, Dataflow allows you to create a task that will be scheduled when all of
|
192
|
+
its data dependencies are available.~~ Replaced by
|
193
|
+
[Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html).
|
194
|
+
* ~~[Promise](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promise.html): Similar
|
195
|
+
to Futures, with more features.~~ Replaced by
|
196
|
+
[Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html).
|
197
|
+
* ~~[Delay](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Delay.html) Lazy evaluation
|
198
|
+
of a block yielding an immutable result. Based on Clojure's
|
199
|
+
[delay](https://clojuredocs.org/clojure.core/delay).~~ Replaced by
|
200
|
+
[Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html).
|
201
|
+
* ~~[IVar](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/IVar.html) Similar to a
|
202
|
+
"future" but can be manually assigned once, after which it becomes immutable.~~ Replaced by
|
203
|
+
[Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html).
|
204
|
+
|
205
|
+
### Edge Features
|
206
|
+
|
207
|
+
These are available in the `concurrent-ruby-edge` companion gem.
|
208
|
+
|
209
|
+
These features are under active development and may change frequently. They are expected not to
|
210
|
+
keep backward compatibility (there may also lack tests and documentation). Semantic versions will
|
211
|
+
be obeyed though. Features developed in `concurrent-ruby-edge` are expected to move to
|
212
|
+
`concurrent-ruby` when final.
|
213
|
+
|
214
|
+
* [Actor](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Actor.html): Implements
|
215
|
+
the Actor Model, where concurrent actors exchange messages.
|
216
|
+
*Status: Partial documentation and tests; depends on new future/promise framework; stability is good.*
|
217
|
+
* [Channel](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Channel.html):
|
218
|
+
Communicating Sequential Processes ([CSP](https://en.wikipedia.org/wiki/Communicating_sequential_processes)).
|
219
|
+
Functionally equivalent to Go [channels](https://tour.golang.org/concurrency/2) with additional
|
220
|
+
inspiration from Clojure [core.async](https://clojure.github.io/core.async/).
|
221
|
+
*Status: Partial documentation and tests.*
|
222
|
+
* [LazyRegister](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/LazyRegister.html)
|
223
|
+
* [LockFreeLinkedSet](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Edge/LockFreeLinkedSet.html)
|
224
|
+
*Status: will be moved to core soon.*
|
225
|
+
* [LockFreeStack](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/LockFreeStack.html)
|
226
|
+
*Status: missing documentation and tests.*
|
227
|
+
* [Promises::Channel](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises/Channel.html)
|
228
|
+
A first in first out channel that accepts messages with push family of methods and returns
|
229
|
+
messages with pop family of methods.
|
230
|
+
Pop and push operations can be represented as futures, see `#pop_op` and `#push_op`.
|
231
|
+
The capacity of the channel can be limited to support back pressure, use capacity option in `#initialize`.
|
232
|
+
`#pop` method blocks ans `#pop_op` returns pending future if there is no message in the channel.
|
233
|
+
If the capacity is limited the `#push` method blocks and `#push_op` returns pending future.
|
234
|
+
* [Cancellation](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Cancellation.html)
|
235
|
+
The Cancellation abstraction provides cooperative cancellation.
|
236
|
+
|
237
|
+
The standard methods `Thread#raise` of `Thread#kill` available in Ruby
|
238
|
+
are very dangerous (see linked the blog posts bellow).
|
239
|
+
Therefore concurrent-ruby provides an alternative.
|
240
|
+
|
241
|
+
* <https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/>
|
242
|
+
* <http://www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/>
|
243
|
+
* <http://blog.headius.com/2008/02/rubys-threadraise-threadkill-timeoutrb.html>
|
244
|
+
|
245
|
+
It provides an object which represents a task which can be executed,
|
246
|
+
the task has to get the reference to the object and periodically cooperatively check that it is not cancelled.
|
247
|
+
Good practices to make tasks cancellable:
|
248
|
+
* check cancellation every cycle of a loop which does significant work,
|
249
|
+
* do all blocking actions in a loop with a timeout then on timeout check cancellation
|
250
|
+
and if ok block again with the timeout
|
251
|
+
* [Throttle](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Throttle.html)
|
252
|
+
A tool managing concurrency level of tasks.
|
253
|
+
* [ErlangActor](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ErlangActor.html)
|
254
|
+
Actor implementation which precisely matches Erlang actor behaviour.
|
255
|
+
Requires at least Ruby 2.1 otherwise it's not loaded.
|
256
|
+
|
257
|
+
## Supported Ruby versions
|
258
|
+
|
259
|
+
* MRI 2.0 and above
|
260
|
+
* JRuby 9000
|
261
|
+
* TruffleRuby are supported.
|
262
|
+
* Any Ruby interpreter that is compliant with Ruby 2.0 or newer.
|
263
|
+
|
264
|
+
Actually we still support mri 1.9.3 and jruby 1.7.27 but we are looking at ways how to drop the support.
|
265
|
+
Java 8 is preferred for JRuby but every Java version on which JRuby 9000 runs is supported.
|
266
|
+
|
267
|
+
The legacy support for Rubinius is kept but it is no longer maintained, if you would like to help
|
268
|
+
please respond to [#739](https://github.com/ruby-concurrency/concurrent-ruby/issues/739).
|
269
|
+
|
270
|
+
## Usage
|
271
|
+
|
272
|
+
Everything within this gem can be loaded simply by requiring it:
|
273
|
+
|
274
|
+
```ruby
|
275
|
+
require 'concurrent'
|
276
|
+
```
|
277
|
+
|
278
|
+
*Requiring only specific abstractions from Concurrent Ruby is not yet supported.*
|
279
|
+
|
280
|
+
To use the tools in the Edge gem it must be required separately:
|
281
|
+
|
282
|
+
```ruby
|
283
|
+
require 'concurrent-edge'
|
284
|
+
```
|
285
|
+
|
286
|
+
If the library does not behave as expected, `Concurrent.use_stdlib_logger(Logger::DEBUG)` could
|
287
|
+
help to reveal the problem.
|
288
|
+
|
289
|
+
## Installation
|
290
|
+
|
291
|
+
```shell
|
292
|
+
gem install concurrent-ruby
|
293
|
+
```
|
294
|
+
|
295
|
+
or add the following line to Gemfile:
|
296
|
+
|
297
|
+
```ruby
|
298
|
+
gem 'concurrent-ruby', require: 'concurrent'
|
299
|
+
```
|
300
|
+
|
301
|
+
and run `bundle install` from your shell.
|
302
|
+
|
303
|
+
### Edge Gem Installation
|
304
|
+
|
305
|
+
The Edge gem must be installed separately from the core gem:
|
306
|
+
|
307
|
+
```shell
|
308
|
+
gem install concurrent-ruby-edge
|
309
|
+
```
|
310
|
+
|
311
|
+
or add the following line to Gemfile:
|
312
|
+
|
313
|
+
```ruby
|
314
|
+
gem 'concurrent-ruby-edge', require: 'concurrent-edge'
|
315
|
+
```
|
316
|
+
|
317
|
+
and run `bundle install` from your shell.
|
318
|
+
|
319
|
+
|
320
|
+
### C Extensions for MRI
|
321
|
+
|
322
|
+
Potential performance improvements may be achieved under MRI by installing optional C extensions.
|
323
|
+
To minimise installation errors the C extensions are available in the `concurrent-ruby-ext`
|
324
|
+
extension gem. `concurrent-ruby` and `concurrent-ruby-ext` are always released together with same
|
325
|
+
version. Simply install the extension gem too:
|
326
|
+
|
327
|
+
```ruby
|
328
|
+
gem install concurrent-ruby-ext
|
329
|
+
```
|
330
|
+
|
331
|
+
or add the following line to Gemfile:
|
332
|
+
|
333
|
+
```ruby
|
334
|
+
gem 'concurrent-ruby-ext'
|
335
|
+
```
|
336
|
+
|
337
|
+
and run `bundle install` from your shell.
|
338
|
+
|
339
|
+
In code it is only necessary to
|
340
|
+
|
341
|
+
```ruby
|
342
|
+
require 'concurrent'
|
343
|
+
```
|
344
|
+
|
345
|
+
The `concurrent-ruby` gem will automatically detect the presence of the `concurrent-ruby-ext` gem
|
346
|
+
and load the appropriate C extensions.
|
347
|
+
|
348
|
+
#### Note For gem developers
|
349
|
+
|
350
|
+
No gems should depend on `concurrent-ruby-ext`. Doing so will force C extensions on your users. The
|
351
|
+
best practice is to depend on `concurrent-ruby` and let users to decide if they want C extensions.
|
352
|
+
|
353
|
+
## Maintainers
|
354
|
+
|
355
|
+
* [Petr Chalupa](https://github.com/pitr-ch) (lead maintainer, point-of-contact)
|
356
|
+
* [Jerry D'Antonio](https://github.com/jdantonio) (creator)
|
357
|
+
* [Chris Seaton](https://github.com/chrisseaton)
|
358
|
+
|
359
|
+
### Special Thanks to
|
360
|
+
|
361
|
+
* [Brian Durand](https://github.com/bdurand) for the `ref` gem
|
362
|
+
* [Charles Oliver Nutter](https://github.com/headius) for the `atomic` and `thread_safe` gems
|
363
|
+
* [thedarkone](https://github.com/thedarkone) for the `thread_safe` gem
|
364
|
+
|
365
|
+
and to the past maintainers
|
366
|
+
|
367
|
+
* [Michele Della Torre](https://github.com/mighe)
|
368
|
+
* [Paweł Obrok](https://github.com/obrok)
|
369
|
+
* [Lucas Allan](https://github.com/lucasallan)
|
370
|
+
|
371
|
+
and to [Ruby Association](https://www.ruby.or.jp/en/) for sponsoring a project
|
372
|
+
["Enhancing Ruby’s concurrency tooling"](https://www.ruby.or.jp/en/news/20181106) in 2018.
|
373
|
+
|
374
|
+
## License and Copyright
|
375
|
+
|
376
|
+
*Concurrent Ruby* is free software released under the
|
377
|
+
[MIT License](http://www.opensource.org/licenses/MIT).
|
378
|
+
|
379
|
+
The *Concurrent Ruby* [logo](https://raw.githubusercontent.com/ruby-concurrency/concurrent-ruby/master/docs-source/logo/concurrent-ruby-logo-300x300.png) was
|
380
|
+
designed by [David Jones](https://twitter.com/zombyboy). It is Copyright © 2014
|
381
|
+
[Jerry D'Antonio](https://twitter.com/jerrydantonio). All Rights Reserved.
|
data/Rakefile
ADDED
@@ -0,0 +1,327 @@
|
|
1
|
+
require_relative 'lib/concurrent/version'
|
2
|
+
require_relative 'lib/concurrent/utility/engine'
|
3
|
+
|
4
|
+
if Concurrent.ruby_version :<, 2, 0, 0
|
5
|
+
# @!visibility private
|
6
|
+
module Kernel
|
7
|
+
def __dir__
|
8
|
+
File.dirname __FILE__
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
core_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby.gemspec')
|
14
|
+
ext_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-ext.gemspec')
|
15
|
+
edge_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-edge.gemspec')
|
16
|
+
|
17
|
+
require 'rake/javaextensiontask'
|
18
|
+
|
19
|
+
Rake::JavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext|
|
20
|
+
ext.ext_dir = 'ext/concurrent-ruby'
|
21
|
+
ext.lib_dir = 'lib/concurrent'
|
22
|
+
end
|
23
|
+
|
24
|
+
unless Concurrent.on_jruby?
|
25
|
+
require 'rake/extensiontask'
|
26
|
+
|
27
|
+
Rake::ExtensionTask.new('concurrent_ruby_ext', ext_gemspec) do |ext|
|
28
|
+
ext.ext_dir = 'ext/concurrent-ruby-ext'
|
29
|
+
ext.lib_dir = 'lib/concurrent'
|
30
|
+
ext.source_pattern = '*.{c,h}'
|
31
|
+
|
32
|
+
ext.cross_compile = true
|
33
|
+
ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
require 'rake_compiler_dock'
|
38
|
+
namespace :repackage do
|
39
|
+
desc '* with Windows fat distributions'
|
40
|
+
task :all do
|
41
|
+
Dir.chdir(__dir__) do
|
42
|
+
# store gems in vendor cache for docker
|
43
|
+
sh 'bundle package'
|
44
|
+
|
45
|
+
# build only the jar file not the whole gem for java platform, the jar is part the concurrent-ruby-x.y.z.gem
|
46
|
+
Rake::Task['lib/concurrent/concurrent_ruby.jar'].invoke
|
47
|
+
|
48
|
+
# build all gem files
|
49
|
+
RakeCompilerDock.sh 'bundle install --local && bundle exec rake cross native package --trace'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
require 'rubygems'
|
55
|
+
require 'rubygems/package_task'
|
56
|
+
|
57
|
+
Gem::PackageTask.new(core_gemspec) {} if core_gemspec
|
58
|
+
Gem::PackageTask.new(ext_gemspec) {} if ext_gemspec && !Concurrent.on_jruby?
|
59
|
+
Gem::PackageTask.new(edge_gemspec) {} if edge_gemspec
|
60
|
+
|
61
|
+
CLEAN.include('lib/concurrent/2.*', 'lib/concurrent/*.jar')
|
62
|
+
|
63
|
+
begin
|
64
|
+
require 'rspec'
|
65
|
+
require 'rspec/core/rake_task'
|
66
|
+
|
67
|
+
RSpec::Core::RakeTask.new(:spec)
|
68
|
+
|
69
|
+
namespace :spec do
|
70
|
+
desc '* Configured for ci'
|
71
|
+
RSpec::Core::RakeTask.new(:ci) do |t|
|
72
|
+
options = %w[ --color
|
73
|
+
--backtrace
|
74
|
+
--order defined
|
75
|
+
--format documentation
|
76
|
+
--tag ~notravis ]
|
77
|
+
t.rspec_opts = [*options].join(' ')
|
78
|
+
end
|
79
|
+
|
80
|
+
desc '* test packaged and installed gems instead of local files'
|
81
|
+
task :installed do
|
82
|
+
Dir.chdir(__dir__) do
|
83
|
+
sh "gem install pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
|
84
|
+
sh "gem install pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem" if Concurrent.on_cruby?
|
85
|
+
sh "gem install pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem"
|
86
|
+
ENV['NO_PATH'] = 'true'
|
87
|
+
sh 'bundle update'
|
88
|
+
sh 'bundle exec rake spec:ci'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
desc 'executed in CI'
|
94
|
+
task :ci => [:compile, 'spec:ci']
|
95
|
+
|
96
|
+
task :default => [:clobber, :compile, :spec]
|
97
|
+
rescue LoadError => e
|
98
|
+
puts 'RSpec is not installed, skipping test task definitions: ' + e.message
|
99
|
+
end
|
100
|
+
|
101
|
+
current_yard_version_name = Concurrent::VERSION
|
102
|
+
|
103
|
+
begin
|
104
|
+
require 'yard'
|
105
|
+
require 'md_ruby_eval'
|
106
|
+
require_relative 'support/yard_full_types'
|
107
|
+
|
108
|
+
common_yard_options = ['--no-yardopts',
|
109
|
+
'--no-document',
|
110
|
+
'--no-private',
|
111
|
+
'--embed-mixins',
|
112
|
+
'--markup', 'markdown',
|
113
|
+
'--title', 'Concurrent Ruby',
|
114
|
+
'--template', 'default',
|
115
|
+
'--template-path', 'yard-template',
|
116
|
+
'--default-return', 'undocumented']
|
117
|
+
|
118
|
+
desc 'Generate YARD Documentation (signpost, master)'
|
119
|
+
task :yard => ['yard:signpost', 'yard:master']
|
120
|
+
|
121
|
+
namespace :yard do
|
122
|
+
|
123
|
+
desc '* eval markdown files'
|
124
|
+
task :eval_md do
|
125
|
+
Dir.chdir File.join(__dir__, 'docs-source') do
|
126
|
+
sh 'bundle exec md-ruby-eval --auto'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
task :update_readme do
|
131
|
+
Dir.chdir __dir__ do
|
132
|
+
content = File.read(File.join('README.md')).
|
133
|
+
gsub(/\[([\w ]+)\]\(http:\/\/ruby-concurrency\.github\.io\/concurrent-ruby\/master\/.*\)/) do |_|
|
134
|
+
case $1
|
135
|
+
when 'LockFreeLinkedSet'
|
136
|
+
"{Concurrent::Edge::#{$1} #{$1}}"
|
137
|
+
when '.dataflow'
|
138
|
+
'{Concurrent.dataflow Concurrent.dataflow}'
|
139
|
+
when 'thread pool'
|
140
|
+
'{file:thread_pools.md thread pool}'
|
141
|
+
else
|
142
|
+
"{Concurrent::#{$1} #{$1}}"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
FileUtils.mkpath 'tmp'
|
146
|
+
File.write 'tmp/README.md', content
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
define_yard_task = -> name do
|
151
|
+
output_dir = "docs/#{name}"
|
152
|
+
|
153
|
+
removal_name = "remove.#{name}"
|
154
|
+
task removal_name do
|
155
|
+
Dir.chdir __dir__ do
|
156
|
+
FileUtils.rm_rf output_dir
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
desc "* of #{name} into subdir #{name}"
|
161
|
+
YARD::Rake::YardocTask.new(name) do |yard|
|
162
|
+
yard.options.push(
|
163
|
+
'--output-dir', output_dir,
|
164
|
+
'--main', 'tmp/README.md',
|
165
|
+
*common_yard_options)
|
166
|
+
yard.files = ['./lib/**/*.rb',
|
167
|
+
'./lib-edge/**/*.rb',
|
168
|
+
'./ext/concurrent_ruby_ext/**/*.c',
|
169
|
+
'-',
|
170
|
+
'docs-source/thread_pools.md',
|
171
|
+
'docs-source/promises.out.md',
|
172
|
+
'docs-source/medium-example.out.rb',
|
173
|
+
'LICENSE.md',
|
174
|
+
'CHANGELOG.md']
|
175
|
+
end
|
176
|
+
Rake::Task[name].prerequisites.push removal_name, 'yard:eval_md', 'yard:update_readme'
|
177
|
+
end
|
178
|
+
|
179
|
+
define_yard_task.call current_yard_version_name
|
180
|
+
define_yard_task.call 'master'
|
181
|
+
|
182
|
+
desc "* signpost for versions"
|
183
|
+
YARD::Rake::YardocTask.new(:signpost) do |yard|
|
184
|
+
yard.options.push(
|
185
|
+
'--output-dir', 'docs',
|
186
|
+
'--main', 'docs-source/signpost.md',
|
187
|
+
*common_yard_options)
|
188
|
+
yard.files = ['no-lib']
|
189
|
+
end
|
190
|
+
|
191
|
+
define_uptodate_task = -> name do
|
192
|
+
namespace name do
|
193
|
+
desc "** ensure that #{name} generated documentation is matching the source code"
|
194
|
+
task :uptodate do
|
195
|
+
Dir.chdir(__dir__) do
|
196
|
+
begin
|
197
|
+
FileUtils.cp_r 'docs', 'docs-copy', verbose: true
|
198
|
+
Rake::Task["yard:#{name}"].invoke
|
199
|
+
sh 'diff -r docs/ docs-copy/' do |ok, res|
|
200
|
+
unless ok
|
201
|
+
begin
|
202
|
+
STDOUT.puts 'Command failed. Continue? (y/n)'
|
203
|
+
input = STDIN.gets.strip.downcase
|
204
|
+
end until %w(y n).include?(input)
|
205
|
+
exit 1 if input == 'n'
|
206
|
+
end
|
207
|
+
end
|
208
|
+
ensure
|
209
|
+
FileUtils.rm_rf 'docs-copy', verbose: true
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
define_uptodate_task.call current_yard_version_name
|
217
|
+
define_uptodate_task.call 'master'
|
218
|
+
end
|
219
|
+
|
220
|
+
rescue LoadError => e
|
221
|
+
puts 'YARD is not installed, skipping documentation task definitions: ' + e.message
|
222
|
+
end
|
223
|
+
|
224
|
+
desc 'build, test, and publish the gem'
|
225
|
+
task :release => ['release:checks', 'release:build', 'release:test', 'release:publish']
|
226
|
+
|
227
|
+
namespace :release do
|
228
|
+
# Depends on environment of @pitr-ch
|
229
|
+
|
230
|
+
mri_version = '2.5.1'
|
231
|
+
jruby_version = 'jruby-9.1.17.1'
|
232
|
+
|
233
|
+
task :checks => "yard:#{current_yard_version_name}:uptodate" do
|
234
|
+
Dir.chdir(__dir__) do
|
235
|
+
sh 'test -z "$(git status --porcelain)"' do |ok, res|
|
236
|
+
unless ok
|
237
|
+
begin
|
238
|
+
STDOUT.puts 'Command failed. Continue? (y/n)'
|
239
|
+
input = STDIN.gets.strip.downcase
|
240
|
+
end until %w(y n).include?(input)
|
241
|
+
exit 1 if input == 'n'
|
242
|
+
end
|
243
|
+
end
|
244
|
+
sh 'git fetch'
|
245
|
+
sh 'test $(git show-ref --verify --hash refs/heads/master) = ' +
|
246
|
+
'$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
|
247
|
+
unless ok
|
248
|
+
begin
|
249
|
+
STDOUT.puts 'Command failed. Continue? (y/n)'
|
250
|
+
input = STDIN.gets.strip.downcase
|
251
|
+
end until %w(y n).include?(input)
|
252
|
+
exit 1 if input == 'n'
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
desc '* build all *.gem files necessary for release'
|
259
|
+
task :build => [:clobber, 'repackage:all']
|
260
|
+
|
261
|
+
desc '* test actual installed gems instead of cloned repository on MRI and JRuby'
|
262
|
+
task :test do
|
263
|
+
Dir.chdir(__dir__) do
|
264
|
+
old = ENV['RBENV_VERSION']
|
265
|
+
|
266
|
+
ENV['RBENV_VERSION'] = mri_version
|
267
|
+
sh 'rbenv version'
|
268
|
+
sh 'bundle exec rake spec:installed'
|
269
|
+
|
270
|
+
ENV['RBENV_VERSION'] = jruby_version
|
271
|
+
sh 'rbenv version'
|
272
|
+
sh 'bundle exec rake spec:installed'
|
273
|
+
|
274
|
+
puts 'Windows build is untested'
|
275
|
+
|
276
|
+
ENV['RBENV_VERSION'] = old
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
desc '* do all nested steps'
|
281
|
+
task :publish => ['publish:ask', 'publish:tag', 'publish:rubygems', 'publish:post_steps']
|
282
|
+
|
283
|
+
namespace :publish do
|
284
|
+
publish_edge = false
|
285
|
+
|
286
|
+
task :ask do
|
287
|
+
begin
|
288
|
+
STDOUT.puts 'Do you want to publish anything? (y/n)'
|
289
|
+
input = STDIN.gets.strip.downcase
|
290
|
+
end until %w(y n).include?(input)
|
291
|
+
exit 1 if input == 'n'
|
292
|
+
begin
|
293
|
+
STDOUT.puts 'Do you want to publish edge? (y/n)'
|
294
|
+
input = STDIN.gets.strip.downcase
|
295
|
+
end until %w(y n).include?(input)
|
296
|
+
publish_edge = input == 'y'
|
297
|
+
end
|
298
|
+
|
299
|
+
desc '** tag HEAD with current version and push to github'
|
300
|
+
task :tag do
|
301
|
+
Dir.chdir(__dir__) do
|
302
|
+
sh "git tag v#{Concurrent::VERSION}"
|
303
|
+
sh "git push origin v#{Concurrent::VERSION}"
|
304
|
+
sh "git tag edge-v#{Concurrent::EDGE_VERSION}" if publish_edge
|
305
|
+
sh "git push origin edge-v#{Concurrent::EDGE_VERSION}" if publish_edge
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
desc '** push all *.gem files to rubygems'
|
310
|
+
task :rubygems do
|
311
|
+
Dir.chdir(__dir__) do
|
312
|
+
sh "gem push pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
|
313
|
+
sh "gem push pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem" if publish_edge
|
314
|
+
sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem"
|
315
|
+
sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x64-mingw32.gem"
|
316
|
+
sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x86-mingw32.gem"
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
desc '** print post release steps'
|
321
|
+
task :post_steps do
|
322
|
+
puts 'Manually: create a release on GitHub with relevant changelog part'
|
323
|
+
puts 'Manually: send email same as release with relevant changelog part'
|
324
|
+
puts 'Manually: tweet'
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|