concurrent-ruby 0.7.2 → 0.8.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
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