concurrent-ruby 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +478 -0
  3. data/Gemfile +41 -0
  4. data/LICENSE.md +23 -0
  5. data/README.md +381 -0
  6. data/Rakefile +327 -0
  7. data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
  10. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
  11. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
  12. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +159 -0
  13. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +307 -0
  14. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
  15. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
  16. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
  17. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
  18. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
  19. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
  20. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
  21. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
  22. data/lib/concurrent-ruby.rb +1 -0
  23. data/lib/concurrent.rb +134 -0
  24. data/lib/concurrent/agent.rb +587 -0
  25. data/lib/concurrent/array.rb +66 -0
  26. data/lib/concurrent/async.rb +459 -0
  27. data/lib/concurrent/atom.rb +222 -0
  28. data/lib/concurrent/atomic/abstract_thread_local_var.rb +66 -0
  29. data/lib/concurrent/atomic/atomic_boolean.rb +126 -0
  30. data/lib/concurrent/atomic/atomic_fixnum.rb +143 -0
  31. data/lib/concurrent/atomic/atomic_markable_reference.rb +164 -0
  32. data/lib/concurrent/atomic/atomic_reference.rb +204 -0
  33. data/lib/concurrent/atomic/count_down_latch.rb +100 -0
  34. data/lib/concurrent/atomic/cyclic_barrier.rb +128 -0
  35. data/lib/concurrent/atomic/event.rb +109 -0
  36. data/lib/concurrent/atomic/java_count_down_latch.rb +42 -0
  37. data/lib/concurrent/atomic/java_thread_local_var.rb +37 -0
  38. data/lib/concurrent/atomic/mutex_atomic_boolean.rb +62 -0
  39. data/lib/concurrent/atomic/mutex_atomic_fixnum.rb +75 -0
  40. data/lib/concurrent/atomic/mutex_count_down_latch.rb +44 -0
  41. data/lib/concurrent/atomic/mutex_semaphore.rb +115 -0
  42. data/lib/concurrent/atomic/read_write_lock.rb +254 -0
  43. data/lib/concurrent/atomic/reentrant_read_write_lock.rb +379 -0
  44. data/lib/concurrent/atomic/ruby_thread_local_var.rb +161 -0
  45. data/lib/concurrent/atomic/semaphore.rb +145 -0
  46. data/lib/concurrent/atomic/thread_local_var.rb +104 -0
  47. data/lib/concurrent/atomic_reference/mutex_atomic.rb +56 -0
  48. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +28 -0
  49. data/lib/concurrent/atomics.rb +10 -0
  50. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +107 -0
  51. data/lib/concurrent/collection/copy_on_write_observer_set.rb +111 -0
  52. data/lib/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
  53. data/lib/concurrent/collection/lock_free_stack.rb +158 -0
  54. data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
  55. data/lib/concurrent/collection/map/mri_map_backend.rb +66 -0
  56. data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +140 -0
  57. data/lib/concurrent/collection/map/synchronized_map_backend.rb +82 -0
  58. data/lib/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
  59. data/lib/concurrent/collection/ruby_non_concurrent_priority_queue.rb +150 -0
  60. data/lib/concurrent/concern/deprecation.rb +34 -0
  61. data/lib/concurrent/concern/dereferenceable.rb +73 -0
  62. data/lib/concurrent/concern/logging.rb +32 -0
  63. data/lib/concurrent/concern/obligation.rb +220 -0
  64. data/lib/concurrent/concern/observable.rb +110 -0
  65. data/lib/concurrent/concurrent_ruby.jar +0 -0
  66. data/lib/concurrent/configuration.rb +184 -0
  67. data/lib/concurrent/constants.rb +8 -0
  68. data/lib/concurrent/dataflow.rb +81 -0
  69. data/lib/concurrent/delay.rb +199 -0
  70. data/lib/concurrent/errors.rb +69 -0
  71. data/lib/concurrent/exchanger.rb +352 -0
  72. data/lib/concurrent/executor/abstract_executor_service.rb +134 -0
  73. data/lib/concurrent/executor/cached_thread_pool.rb +62 -0
  74. data/lib/concurrent/executor/executor_service.rb +185 -0
  75. data/lib/concurrent/executor/fixed_thread_pool.rb +206 -0
  76. data/lib/concurrent/executor/immediate_executor.rb +66 -0
  77. data/lib/concurrent/executor/indirect_immediate_executor.rb +44 -0
  78. data/lib/concurrent/executor/java_executor_service.rb +91 -0
  79. data/lib/concurrent/executor/java_single_thread_executor.rb +29 -0
  80. data/lib/concurrent/executor/java_thread_pool_executor.rb +123 -0
  81. data/lib/concurrent/executor/ruby_executor_service.rb +78 -0
  82. data/lib/concurrent/executor/ruby_single_thread_executor.rb +22 -0
  83. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +362 -0
  84. data/lib/concurrent/executor/safe_task_executor.rb +35 -0
  85. data/lib/concurrent/executor/serial_executor_service.rb +34 -0
  86. data/lib/concurrent/executor/serialized_execution.rb +107 -0
  87. data/lib/concurrent/executor/serialized_execution_delegator.rb +28 -0
  88. data/lib/concurrent/executor/simple_executor_service.rb +100 -0
  89. data/lib/concurrent/executor/single_thread_executor.rb +56 -0
  90. data/lib/concurrent/executor/thread_pool_executor.rb +87 -0
  91. data/lib/concurrent/executor/timer_set.rb +173 -0
  92. data/lib/concurrent/executors.rb +20 -0
  93. data/lib/concurrent/future.rb +141 -0
  94. data/lib/concurrent/hash.rb +59 -0
  95. data/lib/concurrent/immutable_struct.rb +93 -0
  96. data/lib/concurrent/ivar.rb +207 -0
  97. data/lib/concurrent/map.rb +337 -0
  98. data/lib/concurrent/maybe.rb +229 -0
  99. data/lib/concurrent/mutable_struct.rb +229 -0
  100. data/lib/concurrent/mvar.rb +242 -0
  101. data/lib/concurrent/options.rb +42 -0
  102. data/lib/concurrent/promise.rb +579 -0
  103. data/lib/concurrent/promises.rb +2167 -0
  104. data/lib/concurrent/re_include.rb +58 -0
  105. data/lib/concurrent/scheduled_task.rb +318 -0
  106. data/lib/concurrent/set.rb +66 -0
  107. data/lib/concurrent/settable_struct.rb +129 -0
  108. data/lib/concurrent/synchronization.rb +30 -0
  109. data/lib/concurrent/synchronization/abstract_lockable_object.rb +98 -0
  110. data/lib/concurrent/synchronization/abstract_object.rb +24 -0
  111. data/lib/concurrent/synchronization/abstract_struct.rb +160 -0
  112. data/lib/concurrent/synchronization/condition.rb +60 -0
  113. data/lib/concurrent/synchronization/jruby_lockable_object.rb +13 -0
  114. data/lib/concurrent/synchronization/jruby_object.rb +45 -0
  115. data/lib/concurrent/synchronization/lock.rb +36 -0
  116. data/lib/concurrent/synchronization/lockable_object.rb +74 -0
  117. data/lib/concurrent/synchronization/mri_object.rb +44 -0
  118. data/lib/concurrent/synchronization/mutex_lockable_object.rb +76 -0
  119. data/lib/concurrent/synchronization/object.rb +183 -0
  120. data/lib/concurrent/synchronization/rbx_lockable_object.rb +65 -0
  121. data/lib/concurrent/synchronization/rbx_object.rb +49 -0
  122. data/lib/concurrent/synchronization/truffleruby_object.rb +47 -0
  123. data/lib/concurrent/synchronization/volatile.rb +36 -0
  124. data/lib/concurrent/thread_safe/synchronized_delegator.rb +50 -0
  125. data/lib/concurrent/thread_safe/util.rb +16 -0
  126. data/lib/concurrent/thread_safe/util/adder.rb +74 -0
  127. data/lib/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
  128. data/lib/concurrent/thread_safe/util/data_structures.rb +63 -0
  129. data/lib/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
  130. data/lib/concurrent/thread_safe/util/striped64.rb +246 -0
  131. data/lib/concurrent/thread_safe/util/volatile.rb +75 -0
  132. data/lib/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
  133. data/lib/concurrent/timer_task.rb +334 -0
  134. data/lib/concurrent/tuple.rb +86 -0
  135. data/lib/concurrent/tvar.rb +258 -0
  136. data/lib/concurrent/utility/at_exit.rb +97 -0
  137. data/lib/concurrent/utility/engine.rb +56 -0
  138. data/lib/concurrent/utility/monotonic_time.rb +58 -0
  139. data/lib/concurrent/utility/native_extension_loader.rb +79 -0
  140. data/lib/concurrent/utility/native_integer.rb +53 -0
  141. data/lib/concurrent/utility/processor_counter.rb +158 -0
  142. data/lib/concurrent/version.rb +3 -0
  143. 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
@@ -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
+ ```
@@ -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 &copy; 2014
381
+ [Jerry D'Antonio](https://twitter.com/jerrydantonio). All Rights Reserved.
@@ -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