concurrent-ruby 0.7.2 → 0.8.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a55d9e304bf6ccb28a722933ea815d22d37e2698
4
- data.tar.gz: 449c0ead9d820c15508ba37dfa0c14e1e724b161
3
+ metadata.gz: 92bfafa2b9e5e7a3b60cbf6dd6f785a8f515ae64
4
+ data.tar.gz: 14ca027a5eadd0daa3d10fac49860418bb9cb7bc
5
5
  SHA512:
6
- metadata.gz: 52f70bfa218e39a9a2046412af4d75194b348acb7e4769108b1d3bde8dd50b03d5b51d894ede8526e40272f7888c621947f2f67a222dd9b7c9ec76736126ebd9
7
- data.tar.gz: 0385dabafa663c46e71431eaae4b71436397bd982eafb51d544e48fd6abe299e900c48fa5c3c05b2cf8257b720b956a16663990965cb1ea0897a7ae706bb393a
6
+ metadata.gz: 7fae6fa7ae3849e3d68578eb782e13f1dd2e149260c8ef9a5dc8bef72891af0cce9e82abb697cfe72819a1e1c1385936138b63b73f59dd71fba2c9b1bc47bcb8
7
+ data.tar.gz: 66264191f55ab2064cb527a32c84da91550e47681f0e67856535e72b3cb23875d308b8770ec74adfa921800f9c0ae79d14b2f7f7481e545e648dd98eda9ea36a
@@ -1,19 +1,13 @@
1
- ### Next Release v0.7.2 (24 January 2015)
1
+ ### Next Release v0.7.2 (TBD)
2
2
 
3
- * New `Semaphore` class based on [java.util.concurrent.Semaphore](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html)
4
3
  * New `Promise.all?` and `Promise.any?` class methods
5
4
  * Renamed `:overflow_policy` on thread pools to `:fallback_policy`
6
5
  * Thread pools still accept the `:overflow_policy` option but display a warning
7
6
  * Thread pools now implement `fallback_policy` behavior when not running (rather than universally rejecting tasks)
8
7
  * Fixed minor `set_deref_options` constructor bug in `Promise` class
9
- * Fixed minor `require` bug in `ThreadLocalVar` class
10
- * Fixed race condition bug in `TimerSet` class
11
- * Fixed race condition bug in `TimerSet` class
12
- * Fixed signal bug in `TimerSet#post` method
13
8
  * Numerous non-functional updates to clear warning when running in debug mode
14
9
  * Fixed more intermittently failing tests
15
10
  * Tests now run on new Travis build environment
16
- * Multiple documentation updates
17
11
 
18
12
  ## Current Release v0.7.1 (4 December 2014)
19
13
 
data/README.md CHANGED
@@ -38,9 +38,7 @@
38
38
  ### Supported Ruby versions
39
39
 
40
40
  MRI 1.9.3, 2.0, 2.1, JRuby (1.9 mode), and Rubinius 2.x are supported.
41
- Although native code is used for performance optimizations on some platforms, all functionality
42
- is available in pure Ruby. This gem should be fully compatible with any interpreter that is
43
- compliant with Ruby 1.9.3 or newer.
41
+ This gem should be fully compatible with any interpreter that is compliant with Ruby 1.9.3 or newer.
44
42
 
45
43
  ## Features & Documentation
46
44
 
@@ -54,18 +52,19 @@ This library contains a variety of concurrency abstractions at high and low leve
54
52
 
55
53
  ### High-level, general-purpose asynchronous concurrency abstractions
56
54
 
57
- * [Actor](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Actor.html): Implements the Actor Model, where concurrent actors exchange messages.
58
- * [Agent](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Agent.html): A single atomic value that represents an identity.
59
- * [Async](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Async.html): A mixin module that provides simple asynchronous behavior to any standard class/object or object.
60
- * [Future](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Future.html): An asynchronous operation that produces a value.
61
- * [Dataflow](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Dataflow.html): Built on Futures, Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available.
62
- * [Promise](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promise.html): Similar to Futures, with more features.
63
- * [ScheduledTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ScheduledTask.html): Like a Future scheduled for a specific future time.
55
+ * [Actor](./doc/actor/main.md): Implements the Actor Model, where concurrent actors exchange messages.
56
+ * [Agent](./doc/agent.md): A single atomic value that represents an identity.
57
+ * [Async](./doc/async.md): A mixin module that provides simple asynchronous behavior to any standard class/object or object.
58
+ * [Future](./doc/future.md): An asynchronous operation that produces a value.
59
+ * [Dataflow](./doc/dataflow.md): Built on Futures, Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available.
60
+ * [Promise](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promise.html): Similar to Futures, with more features.
61
+ * [ScheduledTask](./doc/scheduled_task.md): Like a Future scheduled for a specific future time.
64
62
  * [TimerTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TimerTask.html): A Thread that periodically wakes up to perform work at regular intervals.
63
+ * [Channel](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Channel.html): Communicating Sequential Processes (CSP).
65
64
 
66
65
  ### Java-inspired ThreadPools and other executors
67
66
 
68
- * See [ThreadPool](http://ruby-concurrency.github.io/concurrent-ruby/file.thread_pools.html) overview, which also contains a list of other Executors available.
67
+ * See [ThreadPool](./doc/thread_pools.md) overview, which also contains a list of other Executors available.
69
68
 
70
69
  ### Thread-safe Observers
71
70
 
@@ -74,7 +73,6 @@ This library contains a variety of concurrency abstractions at high and low leve
74
73
  * [CopyOnWriteObserverSet](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CopyOnWriteObserverSet.html)
75
74
 
76
75
  ### Thread synchronization classes and algorithms
77
-
78
76
  Lower-level abstractions mainly used as building blocks.
79
77
 
80
78
  * [condition](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Condition.html)
@@ -82,12 +80,10 @@ Lower-level abstractions mainly used as building blocks.
82
80
  * [cyclic barrier](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CyclicBarrier.html)
83
81
  * [event](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Event.html)
84
82
  * [exchanger](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Exchanger.html)
85
- * [semaphore](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Semaphore.html)
86
83
  * [timeout](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent.html#timeout-class_method)
87
84
  * [timer](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent.html#timer-class_method)
88
85
 
89
86
  ### Thread-safe variables
90
-
91
87
  Lower-level abstractions mainly used as building blocks.
92
88
 
93
89
  * [AtomicBoolean](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicBoolean.html)
@@ -96,30 +92,47 @@ Lower-level abstractions mainly used as building blocks.
96
92
  * [I-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/IVar.html) (IVar)
97
93
  * [M-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MVar.html) (MVar)
98
94
  * [thread-local variables](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ThreadLocalVar.html)
99
- * [software transactional memory](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TVar.html) (TVar)
95
+ * [software transactional memory](./doc/tvar.md) (TVar)
100
96
 
101
- ## Installing and Building
97
+ ## Usage
102
98
 
103
- This gem includes several platform-specific optimizations. To reduce the possibility of
104
- compilation errors, we provide pre-compiled gem packages for several platforms as well
105
- as a pure-Ruby build. Installing the gem should be no different than installing any other
106
- Rubygems-hosted gem. Rubygems will automatically detect your platform and install the
107
- appropriate pre-compiled build. You should never see Rubygems attempt to compile the gem
108
- on installation. Additionally, to ensure compatability with the largest possible number
109
- of Ruby interpreters, the C extensions will *never* load under any Ruby other than MRI,
110
- even when installed.
99
+ All abstractions within this gem can be loaded simply by requiring it:
100
+
101
+ ```ruby
102
+ require 'concurrent'
103
+ ```
111
104
 
112
- The following gem builds will be built at every release:
105
+ To reduce the amount of code loaded at runtime, subsets of this gem can be required:
113
106
 
114
- * concurrent-ruby-x.y.z.gem (pure Ruby)
115
- * concurrent-ruby-x.y.z-java.gem (JRuby)
116
- * concurrent-ruby-x.y.z-x86-linux.gem (Linux 32-bit)
117
- * concurrent-ruby-x.y.z-x86_64-linux.gem (Linux 64-bit)
118
- * concurrent-ruby-x.y.z-x86-mingw32.gem (Windows 32-bit)
119
- * concurrent-ruby-x.y.z-x64-mingw32.gem (Windows 64-bit)
120
- * concurrent-ruby-x.y.z-x86-solaris-2.11.gem (Solaris)
107
+ ```ruby
108
+ require 'concurrent' # everything
109
+
110
+ # groups
111
+
112
+ require 'concurrent/actor' # Concurrent::Actor and supporting code
113
+ require 'concurrent/atomics' # atomic and thread synchronization classes
114
+ require 'concurrent/channels' # Concurrent::Channel and supporting code
115
+ require 'concurrent/executors' # Thread pools and other executors
116
+ require 'concurrent/utilities' # utility methods such as processor count and timers
117
+
118
+ # individual abstractions
119
+
120
+ require 'concurrent/agent' # Concurrent::Agent
121
+ require 'concurrent/async' # Concurrent::Async
122
+ require 'concurrent/atomic' # Concurrent::Atomic (formerly the `atomic` gem)
123
+ require 'concurrent/dataflow' # Concurrent::dataflow
124
+ require 'concurrent/delay' # Concurrent::Delay
125
+ require 'concurrent/exchanger' # Concurrent::Exchanger
126
+ require 'concurrent/future' # Concurrent::Future
127
+ require 'concurrent/ivar' # Concurrent::IVar
128
+ require 'concurrent/mvar' # Concurrent::MVar
129
+ require 'concurrent/promise' # Concurrent::Promise
130
+ require 'concurrent/scheduled_task' # Concurrent::ScheduledTask
131
+ require 'concurrent/timer_task' # Concurrent::TimerTask
132
+ require 'concurrent/tvar' # Concurrent::TVar
133
+ ```
121
134
 
122
- ### Installing
135
+ ## Installation
123
136
 
124
137
  ```shell
125
138
  gem install concurrent-ruby
@@ -133,33 +146,34 @@ gem 'concurrent-ruby'
133
146
 
134
147
  and run `bundle install` from your shell.
135
148
 
136
- ### Building
149
+ ### C Extensions for MRI
137
150
 
138
- Because we provide pre-compiled gem builds, users should never need to build the gem manually.
139
- The build process for this gem is completely automated using open source tools. All of
140
- the automation components are available in the [ruby-concurrency/rake-compiler-dev-box](https://github.com/ruby-concurrency/rake-compiler-dev-box)
141
- GitHub repository.
151
+ Potential performance improvements may be achieved under MRI by installing optional C extensions.
152
+ To minimize installation errors the C extensions are available in the `concurrent-ruby-ext` extension
153
+ gem. The extension gem lists `concurrent-ruby` as a dependency so it is not necessary to install both.
154
+ Simply install the extension gen:
142
155
 
143
- This gem will compile native C code under MRI and native Java code under JRuby. It is
144
- also possible to build a pure-Ruby version. All builds have identical functionality.
145
- The only difference is performance. Additionally, pure-Ruby classes are always available,
146
- even when using the native optimizations. Please see the [documentation](http://ruby-concurrency.github.io/concurrent-ruby/)
147
- for more details.
156
+ ```shell
157
+ gem install concurrent-ruby-ext
158
+ ```
148
159
 
149
- To build and package the gem using MRI or JRuby, install the necessary build dependencies and run:
160
+ or add the following line to Gemfile:
150
161
 
151
- ```shell
152
- bundle exec rake compile
153
- bundle exec rake build
162
+ ```ruby
163
+ gem 'concurrent-ruby-ext'
154
164
  ```
155
165
 
156
- To build and package a pure-Ruby gem, on *any* platform and interpreter
157
- (including MRI and JRuby), run:
166
+ and run `bundle install` from your shell.
167
+
168
+ In code it is only necessary to
158
169
 
159
170
  ```shell
160
- BUILD_PURE_RUBY='true' bundle exec rake build
171
+ require 'concurrent'
161
172
  ```
162
173
 
174
+ The `concurrent-ruby` gem will automatically detect the presence of the `concurrent-ruby-ext` gem
175
+ and load the appropriate C extensions.
176
+
163
177
  ## Maintainers
164
178
 
165
179
  * [Jerry D'Antonio](https://github.com/jdantonio)
@@ -167,6 +181,7 @@ BUILD_PURE_RUBY='true' bundle exec rake build
167
181
  * [Chris Seaton](https://github.com/chrisseaton)
168
182
  * [Lucas Allan](https://github.com/lucasallan)
169
183
  * [Petr Chalupa](https://github.com/pitr-ch)
184
+ * [Paweł Obrok](https://github.com/obrok)
170
185
 
171
186
  ### Contributing
172
187
 
@@ -12,6 +12,7 @@ RUBY
12
12
  end
13
13
  #####################################################################
14
14
 
15
+ require_relative '../extension_helper'
15
16
  require 'concurrent/atomic_reference/concurrent_update_error'
16
17
  require 'concurrent/atomic_reference/mutex_atomic'
17
18
 
@@ -77,7 +78,7 @@ elsif defined? Concurrent::RbxAtomic
77
78
  class Concurrent::Atomic < Concurrent::RbxAtomic
78
79
  end
79
80
 
80
- elsif Concurrent.allow_c_native_class?('CAtomic')
81
+ elsif defined? Concurrent::CAtomic
81
82
 
82
83
  # @!macro atomic_reference
83
84
  class Concurrent::Atomic < Concurrent::CAtomic
@@ -1,5 +1,4 @@
1
1
  require_relative '../../extension_helper'
2
- Concurrent.safe_require_c_extensions
3
2
 
4
3
  module Concurrent
5
4
 
@@ -162,7 +161,7 @@ module Concurrent
162
161
  class AtomicBoolean < JavaAtomicBoolean
163
162
  end
164
163
 
165
- elsif Concurrent.allow_c_native_class?('CAtomicBoolean')
164
+ elsif defined?(CAtomicBoolean)
166
165
 
167
166
  # @!macro atomic_boolean
168
167
  class CAtomicBoolean
@@ -1,5 +1,4 @@
1
1
  require_relative '../../extension_helper'
2
- Concurrent.safe_require_c_extensions
3
2
 
4
3
  module Concurrent
5
4
 
@@ -166,7 +165,7 @@ module Concurrent
166
165
  class AtomicFixnum < JavaAtomicFixnum
167
166
  end
168
167
 
169
- elsif Concurrent.allow_c_native_class?('CAtomicFixnum')
168
+ elsif defined?(CAtomicFixnum)
170
169
 
171
170
  # @!macro atomic_fixnum
172
171
  class CAtomicFixnum
@@ -1,5 +1,4 @@
1
1
  require_relative '../../extension_helper'
2
- Concurrent.safe_require_java_extensions
3
2
 
4
3
  if defined?(Concurrent::JavaAtomic)
5
4
  require 'concurrent/atomic_reference/direct_update'
@@ -1,37 +1,29 @@
1
- require_relative '../../extension_helper'
1
+ if defined? Concurrent::CAtomic
2
+ require_relative '../../extension_helper'
3
+ require 'concurrent/atomic_reference/direct_update'
4
+ require 'concurrent/atomic_reference/numeric_cas_wrapper'
2
5
 
3
- if Concurrent.allow_c_extensions?
4
- begin
5
- require 'concurrent_ruby_ext'
6
- rescue LoadError
7
- # may be a Windows cross-compiled native gem
8
- require "#{RUBY_VERSION[0..2]}/concurrent_ruby_ext"
9
- end
10
- end
11
-
12
- require 'concurrent/atomic_reference/direct_update'
13
- require 'concurrent/atomic_reference/numeric_cas_wrapper'
14
-
15
- module Concurrent
6
+ module Concurrent
16
7
 
17
- # @!macro atomic_reference
18
- class CAtomic
19
- include Concurrent::AtomicDirectUpdate
20
- include Concurrent::AtomicNumericCompareAndSetWrapper
8
+ # @!macro atomic_reference
9
+ class CAtomic
10
+ include Concurrent::AtomicDirectUpdate
11
+ include Concurrent::AtomicNumericCompareAndSetWrapper
21
12
 
22
- # @!method initialize
23
- # @!macro atomic_reference_method_initialize
13
+ # @!method initialize
14
+ # @!macro atomic_reference_method_initialize
24
15
 
25
- # @!method get
26
- # @!macro atomic_reference_method_get
16
+ # @!method get
17
+ # @!macro atomic_reference_method_get
27
18
 
28
- # @!method set
29
- # @!macro atomic_reference_method_set
19
+ # @!method set
20
+ # @!macro atomic_reference_method_set
30
21
 
31
- # @!method get_and_set
32
- # @!macro atomic_reference_method_get_and_set
22
+ # @!method get_and_set
23
+ # @!macro atomic_reference_method_get_and_set
33
24
 
34
- # @!method _compare_and_set
35
- # @!macro atomic_reference_method_compare_and_set
25
+ # @!method _compare_and_set
26
+ # @!macro atomic_reference_method_compare_and_set
27
+ end
36
28
  end
37
29
  end
@@ -8,5 +8,3 @@ require 'concurrent/atomic/cyclic_barrier'
8
8
  require 'concurrent/atomic/count_down_latch'
9
9
  require 'concurrent/atomic/event'
10
10
  require 'concurrent/atomic/synchronization'
11
- require 'concurrent/atomic/semaphore'
12
- require 'concurrent/atomic/thread_local_var'
@@ -49,6 +49,8 @@ module Concurrent
49
49
  # * `:discard`: Discard the task and return false.
50
50
  # * `:caller_runs`: Execute the task on the calling thread.
51
51
  #
52
+ # {include:file:doc/thread_pools.md}
53
+ #
52
54
  # @note When running on the JVM (JRuby) this class will inherit from `JavaThreadPoolExecutor`.
53
55
  # On all other platforms it will inherit from `RubyThreadPoolExecutor`.
54
56
  #
@@ -55,10 +55,10 @@ module Concurrent
55
55
  @queue.push(Task.new(time, args, task))
56
56
  @timer_executor.post(&method(:process_tasks))
57
57
  end
58
+
59
+ true
58
60
  end
59
61
 
60
- @condition.signal
61
- true
62
62
  end
63
63
 
64
64
  # For a timer, #kill is like an orderly shutdown, except we need to manually
@@ -129,20 +129,8 @@ module Concurrent
129
129
  interval = task.time - Time.now.to_f
130
130
 
131
131
  if interval <= 0
132
- # We need to remove the task from the queue before passing
133
- # it to the executor, to avoid race conditions where we pass
134
- # the peek'ed task to the executor and then pop a different
135
- # one that's been added in the meantime.
136
- #
137
- # Note that there's no race condition between the peek and
138
- # this pop - this pop could retrieve a different task from
139
- # the peek, but that task would be due to fire now anyway
140
- # (because @queue is a priority queue, and this thread is
141
- # the only reader, so whatever timer is at the head of the
142
- # queue now must have the same pop time, or a closer one, as
143
- # when we peeked).
144
- task = mutex.synchronize { @queue.pop }
145
132
  @task_executor.post(*task.args, &task.op)
133
+ mutex.synchronize { @queue.pop }
146
134
  else
147
135
  mutex.synchronize do
148
136
  @condition.wait(mutex, [interval, 60].min)
@@ -1,3 +1,4 @@
1
1
  module Concurrent
2
- VERSION = '0.7.2'
2
+ VERSION = '0.8.0.pre1'
3
+ EXT_VERSION = '0.1.0.pre1'
3
4
  end
@@ -1,28 +1,32 @@
1
1
  module Concurrent
2
+
3
+ @@c_ext_loaded ||= false
4
+ @@java_ext_loaded ||= false
2
5
 
3
6
  # @!visibility private
4
7
  def self.allow_c_extensions?
5
8
  defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby'
6
9
  end
7
10
 
8
- # @!visibility private
9
- def self.allow_c_native_class?(clazz)
10
- allow_c_extensions? && Concurrent.const_defined?(clazz)
11
- rescue
12
- false
13
- end
14
-
15
- # @!visibility private
16
- def self.safe_require_c_extensions
17
- require 'concurrent_ruby_ext' if allow_c_extensions?
18
- rescue LoadError
19
- #warn 'Attempted to load C extensions on unsupported platform. Continuing with pure-Ruby.'
20
- end
21
-
22
- # @!visibility private
23
- def self.safe_require_java_extensions
24
- require 'concurrent_ruby_ext' if RUBY_PLATFORM == 'java'
25
- rescue LoadError
26
- #warn 'Attempted to load Java extensions on unsupported platform. Continuing with pure-Ruby.'
11
+ if allow_c_extensions? && !@@c_ext_loaded
12
+ begin
13
+ require 'concurrent_ruby_ext'
14
+ @@c_ext_loaded = true
15
+ rescue LoadError
16
+ # may be a Windows cross-compiled native gem
17
+ begin
18
+ require "#{RUBY_VERSION[0..2]}/concurrent_ruby_ext"
19
+ @@c_ext_loaded = true
20
+ rescue LoadError
21
+ warn 'Performance on MRI may be improved with the concurrent-ruby-ext gem. Please see http://concurrent-ruby.com'
22
+ end
23
+ end
24
+ elsif RUBY_PLATFORM == 'java' && !@@java_ext_loaded
25
+ begin
26
+ require 'concurrent_ruby_ext'
27
+ @@java_ext_loaded = true
28
+ rescue LoadError
29
+ #warn 'Attempted to load Java extensions on unsupported platform. Continuing with pure-Ruby.'
30
+ end
27
31
  end
28
32
  end
metadata CHANGED
@@ -1,20 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerry D'Antonio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-24 00:00:00.000000000 Z
11
+ date: 2014-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ref
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ - - ">="
18
21
  - !ruby/object:Gem::Version
19
22
  version: 1.0.5
20
23
  type: :runtime
@@ -22,6 +25,9 @@ dependencies:
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - - ">="
25
31
  - !ruby/object:Gem::Version
26
32
  version: 1.0.5
27
33
  description: |2
@@ -81,7 +87,6 @@ files:
81
87
  - lib/concurrent/atomic/count_down_latch.rb
82
88
  - lib/concurrent/atomic/cyclic_barrier.rb
83
89
  - lib/concurrent/atomic/event.rb
84
- - lib/concurrent/atomic/semaphore.rb
85
90
  - lib/concurrent/atomic/synchronization.rb
86
91
  - lib/concurrent/atomic/thread_local_var.rb
87
92
  - lib/concurrent/atomic_reference/concurrent_update_error.rb
@@ -162,9 +167,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
162
167
  version: 1.9.3
163
168
  required_rubygems_version: !ruby/object:Gem::Requirement
164
169
  requirements:
165
- - - ">="
170
+ - - ">"
166
171
  - !ruby/object:Gem::Version
167
- version: '0'
172
+ version: 1.3.1
168
173
  requirements: []
169
174
  rubyforge_project:
170
175
  rubygems_version: 2.4.5
@@ -1,232 +0,0 @@
1
- require 'concurrent/atomic/condition'
2
-
3
- module Concurrent
4
- class MutexSemaphore
5
- # @!macro [attach] semaphore_method_initialize
6
- #
7
- # Create a new `Semaphore` with the initial `count`.
8
- #
9
- # @param [Fixnum] count the initial count
10
- #
11
- # @raise [ArgumentError] if `count` is not an integer or is less than zero
12
- def initialize(count)
13
- unless count.is_a?(Fixnum) && count >= 0
14
- fail ArgumentError, 'count must be an non-negative integer'
15
- end
16
- @mutex = Mutex.new
17
- @condition = Condition.new
18
- @free = count
19
- end
20
-
21
- # @!macro [attach] semaphore_method_acquire
22
- #
23
- # Acquires the given number of permits from this semaphore,
24
- # blocking until all are available.
25
- #
26
- # @param [Fixnum] permits Number of permits to acquire
27
- #
28
- # @raise [ArgumentError] if `permits` is not an integer or is less than
29
- # one
30
- #
31
- # @return [Nil]
32
- def acquire(permits = 1)
33
- unless permits.is_a?(Fixnum) && permits > 0
34
- fail ArgumentError, 'permits must be an integer greater than zero'
35
- end
36
- @mutex.synchronize do
37
- try_acquire_timed(permits, nil)
38
- nil
39
- end
40
- end
41
-
42
- # @!macro [attach] semaphore_method_available_permits
43
- #
44
- # Returns the current number of permits available in this semaphore.
45
- #
46
- # @return [Integer]
47
- def available_permits
48
- @mutex.synchronize { @free }
49
- end
50
-
51
- # @!macro [attach] semaphore_method_drain_permits
52
- #
53
- # Acquires and returns all permits that are immediately available.
54
- #
55
- # @return [Integer]
56
- def drain_permits
57
- @mutex.synchronize do
58
- @free.tap { |_| @free = 0 }
59
- end
60
- end
61
-
62
- # @!macro [attach] semaphore_method_try_acquire
63
- #
64
- # Acquires the given number of permits from this semaphore,
65
- # only if all are available at the time of invocation or within
66
- # `timeout` interval
67
- #
68
- # @param [Fixnum] permits the number of permits to acquire
69
- #
70
- # @param [Fixnum] timeout the number of seconds to wait for the counter
71
- # or `nil` to return immediately
72
- #
73
- # @raise [ArgumentError] if `permits` is not an integer or is less than
74
- # one
75
- #
76
- # @return [Boolean] `false` if no permits are available, `true` when
77
- # acquired a permit
78
- def try_acquire(permits = 1, timeout = nil)
79
- unless permits.is_a?(Fixnum) && permits > 0
80
- fail ArgumentError, 'permits must be an integer greater than zero'
81
- end
82
- @mutex.synchronize do
83
- if timeout.nil?
84
- try_acquire_now(permits)
85
- else
86
- try_acquire_timed(permits, timeout)
87
- end
88
- end
89
- end
90
-
91
- # @!macro [attach] semaphore_method_release
92
- #
93
- # Releases the given number of permits, returning them to the semaphore.
94
- #
95
- # @param [Fixnum] permits Number of permits to return to the semaphore.
96
- #
97
- # @raise [ArgumentError] if `permits` is not a number or is less than one
98
- #
99
- # @return [Nil]
100
- def release(permits = 1)
101
- unless permits.is_a?(Fixnum) && permits > 0
102
- fail ArgumentError, 'permits must be an integer greater than zero'
103
- end
104
- @mutex.synchronize do
105
- @free += permits
106
- permits.times { @condition.signal }
107
- end
108
- nil
109
- end
110
-
111
- # @!macro [attach] semaphore_method_reduce_permits
112
- #
113
- # @api private
114
- #
115
- # Shrinks the number of available permits by the indicated reduction.
116
- #
117
- # @param [Fixnum] reduction Number of permits to remove.
118
- #
119
- # @raise [ArgumentError] if `reduction` is not an integer or is negative
120
- #
121
- # @raise [ArgumentError] if `@free` - `@reduction` is less than zero
122
- #
123
- # @return [Nil]
124
- def reduce_permits(reduction)
125
- unless reduction.is_a?(Fixnum) && reduction >= 0
126
- fail ArgumentError, 'reduction must be an non-negative integer'
127
- end
128
- @mutex.synchronize { @free -= reduction }
129
- nil
130
- end
131
-
132
- private
133
-
134
- def try_acquire_now(permits)
135
- if @free >= permits
136
- @free -= permits
137
- true
138
- else
139
- false
140
- end
141
- end
142
-
143
- def try_acquire_timed(permits, timeout)
144
- remaining = Condition::Result.new(timeout)
145
- while !try_acquire_now(permits) && remaining.can_wait?
146
- @condition.signal
147
- remaining = @condition.wait(@mutex, remaining.remaining_time)
148
- end
149
- remaining.can_wait? ? true : false
150
- end
151
- end
152
-
153
- if RUBY_PLATFORM == 'java'
154
-
155
- # @!macro semaphore
156
- #
157
- # A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each {#acquire} blocks if necessary
158
- # until a permit is available, and then takes it. Each {#release} adds a permit,
159
- # potentially releasing a blocking acquirer.
160
- # However, no actual permit objects are used; the Semaphore just keeps a count of the number available and
161
- # acts accordingly.
162
- class JavaSemaphore
163
- # @!macro semaphore_method_initialize
164
- def initialize(count)
165
- unless count.is_a?(Fixnum) && count >= 0
166
- fail(ArgumentError,
167
- 'count must be in integer greater than or equal zero')
168
- end
169
- @semaphore = java.util.concurrent.Semaphore.new(count)
170
- end
171
-
172
- # @!macro semaphore_method_acquire
173
- def acquire(permits = 1)
174
- unless permits.is_a?(Fixnum) && permits > 0
175
- fail ArgumentError, 'permits must be an integer greater than zero'
176
- end
177
- @semaphore.acquire(permits)
178
- end
179
-
180
- # @!macro semaphore_method_available_permits
181
- def available_permits
182
- @semaphore.availablePermits
183
- end
184
-
185
- # @!macro semaphore_method_drain_permits
186
- def drain_permits
187
- @semaphore.drainPermits
188
- end
189
-
190
- # @!macro semaphore_method_try_acquire
191
- def try_acquire(permits = 1, timeout = nil)
192
- unless permits.is_a?(Fixnum) && permits > 0
193
- fail ArgumentError, 'permits must be an integer greater than zero'
194
- end
195
- if timeout.nil?
196
- @semaphore.tryAcquire(permits)
197
- else
198
- @semaphore.tryAcquire(permits,
199
- timeout,
200
- java.util.concurrent.TimeUnit::SECONDS)
201
- end
202
- end
203
-
204
- # @!macro semaphore_method_release
205
- def release(permits = 1)
206
- unless permits.is_a?(Fixnum) && permits > 0
207
- fail ArgumentError, 'permits must be an integer greater than zero'
208
- end
209
- @semaphore.release(permits)
210
- true
211
- end
212
-
213
- # @!macro semaphore_method_reduce_permits
214
- def reduce_permits(reduction)
215
- unless reduction.is_a?(Fixnum) && reduction >= 0
216
- fail ArgumentError, 'reduction must be an non-negative integer'
217
- end
218
- @semaphore.reducePermits(reduction)
219
- end
220
- end
221
-
222
- # @!macro semaphore
223
- class Semaphore < JavaSemaphore
224
- end
225
-
226
- else
227
-
228
- # @!macro semaphore
229
- class Semaphore < MutexSemaphore
230
- end
231
- end
232
- end