concurrent-ruby 0.7.0.rc0-java → 0.7.0.rc1-java
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.
- data/README.md +13 -8
- data/lib/concurrent.rb +0 -1
- data/lib/concurrent/actress.rb +10 -6
- data/lib/concurrent/actress/core.rb +1 -1
- data/lib/concurrent/async.rb +39 -74
- data/lib/concurrent/atomic.rb +21 -1
- data/lib/concurrent/atomic_reference/concurrent_update_error.rb +1 -0
- data/lib/concurrent/atomic_reference/direct_update.rb +22 -0
- data/lib/concurrent/atomic_reference/jruby.rb +2 -0
- data/lib/concurrent/atomic_reference/mutex_atomic.rb +36 -6
- data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +8 -7
- data/lib/concurrent/atomic_reference/rbx.rb +7 -4
- data/lib/concurrent/atomic_reference/ruby.rb +2 -0
- data/lib/concurrent/executor/executor.rb +118 -70
- data/lib/concurrent/executor/immediate_executor.rb +50 -1
- data/lib/concurrent/executor/java_fixed_thread_pool.rb +14 -6
- data/lib/concurrent/executor/java_single_thread_executor.rb +1 -0
- data/lib/concurrent/executor/java_thread_pool_executor.rb +3 -10
- data/lib/concurrent/executor/per_thread_executor.rb +80 -4
- data/lib/concurrent/executor/ruby_cached_thread_pool.rb +1 -1
- data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +4 -4
- data/lib/concurrent/executor/ruby_single_thread_executor.rb +1 -0
- data/lib/concurrent/executor/ruby_thread_pool_executor.rb +2 -0
- data/lib/concurrent/executor/serialized_execution.rb +23 -0
- data/lib/concurrent/version.rb +1 -1
- data/lib/concurrent_ruby_ext.bundle +0 -0
- data/lib/concurrent_ruby_ext.jar +0 -0
- metadata +2 -4
- data/lib/concurrent/atomic_reference/delegated_update.rb +0 -28
- data/lib/concurrent/supervisor.rb +0 -343
    
        data/README.md
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            # Concurrent Ruby
         | 
| 2 | 
            -
            [](http://badge.fury.io/rb/concurrent-ruby) [](https://travis-ci.org/ruby-concurrency/concurrent-ruby) [](https://coveralls.io/r/ruby-concurrency/concurrent-ruby) [](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby) [](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby) [](https://gemnasium.com/ruby-concurrency/concurrent-ruby)
         | 
| 2 | 
            +
            [](http://badge.fury.io/rb/concurrent-ruby) [](https://travis-ci.org/ruby-concurrency/concurrent-ruby) [](https://coveralls.io/r/ruby-concurrency/concurrent-ruby) [](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby) [](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby) [](https://gemnasium.com/ruby-concurrency/concurrent-ruby) [](https://gitter.im/ruby-concurrency)
         | 
| 3 3 |  | 
| 4 4 | 
             
            <table>
         | 
| 5 5 | 
             
              <tr>
         | 
| @@ -67,8 +67,6 @@ into several general groups: | |
| 67 67 | 
             
              [Promise](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Promise),
         | 
| 68 68 | 
             
              [ScheduledTask](https://github.com/ruby-concurrency/concurrent-ruby/wiki/ScheduledTask),
         | 
| 69 69 | 
             
              and [TimerTask](https://github.com/ruby-concurrency/concurrent-ruby/wiki/TimerTask) 
         | 
| 70 | 
            -
            * Erlang-inspired [Supervisor](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Supervisor) and other lifecycle classes/mixins
         | 
| 71 | 
            -
              for managing long-running threads
         | 
| 72 70 | 
             
            * Thread-safe variables including [M-Structures](https://github.com/ruby-concurrency/concurrent-ruby/wiki/MVar-(M-Structure)),
         | 
| 73 71 | 
             
              [I-Structures](https://github.com/ruby-concurrency/concurrent-ruby/wiki/IVar-(I-Structure)),
         | 
| 74 72 | 
             
              [thread-local variables](https://github.com/ruby-concurrency/concurrent-ruby/wiki/ThreadLocalVar),
         | 
| @@ -133,23 +131,30 @@ sleep(3)   # do other stuff | |
| 133 131 | 
             
            task.value #=> 25.96
         | 
| 134 132 | 
             
            ```
         | 
| 135 133 |  | 
| 136 | 
            -
            ##  | 
| 134 | 
            +
            ## Maintainers
         | 
| 137 135 |  | 
| 138 136 | 
             
            * [Jerry D'Antonio](https://github.com/jdantonio)
         | 
| 139 137 | 
             
            * [Michele Della Torre](https://github.com/mighe)
         | 
| 140 138 | 
             
            * [Chris Seaton](https://github.com/chrisseaton)
         | 
| 141 139 | 
             
            * [Lucas Allan](https://github.com/lucasallan)
         | 
| 142 140 | 
             
            * [Petr Chalupa](https://github.com/pitr-ch)
         | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 141 | 
            +
             | 
| 142 | 
            +
            ### Contributors
         | 
| 143 | 
            +
             | 
| 146 144 | 
             
            * [Bill Dueber](https://github.com/billdueber)
         | 
| 147 145 | 
             
            * [Brian Shirai](https://github.com/brixen)
         | 
| 148 146 | 
             
            * [Chip Miller](https://github.com/chip-miller)
         | 
| 147 | 
            +
            * [Giuseppe Capizzi](https://github.com/gcapizzi)
         | 
| 149 148 | 
             
            * [Jamie Hodge](https://github.com/jamiehodge)
         | 
| 149 | 
            +
            * [Larry Lv](https://github.com/larrylv)
         | 
| 150 | 
            +
            * [Maxim Chechel](https://github.com/maximchick)
         | 
| 151 | 
            +
            * [Ravil Bayramgalin](https://github.com/brainopia)
         | 
| 152 | 
            +
            * [René Föhring](https://github.com/rrrene)
         | 
| 153 | 
            +
            * [Shane Wilton](https://github.com/ShaneWilton)
         | 
| 154 | 
            +
            * [sheaney](https://github.com/sheaney)
         | 
| 150 155 | 
             
            * [Zander Hill](https://github.com/zph)
         | 
| 151 156 |  | 
| 152 | 
            -
             | 
| 157 | 
            +
            ### Contributing
         | 
| 153 158 |  | 
| 154 159 | 
             
            1. Fork it
         | 
| 155 160 | 
             
            2. Create your feature branch (`git checkout -b my-new-feature`)
         | 
    
        data/lib/concurrent.rb
    CHANGED
    
    
    
        data/lib/concurrent/actress.rb
    CHANGED
    
    | @@ -11,8 +11,8 @@ module Concurrent | |
| 11 11 | 
             
              # -  Inspired by Akka and Erlang.
         | 
| 12 12 | 
             
              #
         | 
| 13 13 | 
             
              # Actors are sharing a thread-pool by default which makes them very cheap to create and discard.
         | 
| 14 | 
            -
              # Thousands of actors can be created allowing to  | 
| 15 | 
            -
              # without  | 
| 14 | 
            +
              # Thousands of actors can be created, allowing you to break the program into small maintainable pieces,
         | 
| 15 | 
            +
              # without violating the single responsibility principle.
         | 
| 16 16 | 
             
              #
         | 
| 17 17 | 
             
              # ## What is an actor model?
         | 
| 18 18 | 
             
              #
         | 
| @@ -26,7 +26,7 @@ module Concurrent | |
| 26 26 | 
             
              # ## Why?
         | 
| 27 27 | 
             
              #
         | 
| 28 28 | 
             
              # Concurrency is hard this is one of many ways how to simplify the problem.
         | 
| 29 | 
            -
              # It is simpler to reason about actors  | 
| 29 | 
            +
              # It is simpler to reason about actors than about locks (and all their possible states).
         | 
| 30 30 | 
             
              #
         | 
| 31 31 | 
             
              # ## How to use it
         | 
| 32 32 | 
             
              #
         | 
| @@ -145,7 +145,7 @@ module Concurrent | |
| 145 145 | 
             
                  Thread.current[:__current_actor__]
         | 
| 146 146 | 
             
                end
         | 
| 147 147 |  | 
| 148 | 
            -
                # implements  | 
| 148 | 
            +
                # implements the root actor
         | 
| 149 149 | 
             
                class Root
         | 
| 150 150 | 
             
                  include Context
         | 
| 151 151 | 
             
                  # to allow spawning of new actors, spawn needs to be called inside the parent Actor
         | 
| @@ -158,8 +158,12 @@ module Concurrent | |
| 158 158 | 
             
                  end
         | 
| 159 159 | 
             
                end
         | 
| 160 160 |  | 
| 161 | 
            +
                @root = Delay.new { Core.new(parent: nil, name: '/', class: Root).reference }
         | 
| 162 | 
            +
             | 
| 161 163 | 
             
                # A root actor, a default parent of all actors spawned outside an actor
         | 
| 162 | 
            -
                 | 
| 164 | 
            +
                def self.root
         | 
| 165 | 
            +
                  @root.value
         | 
| 166 | 
            +
                end
         | 
| 163 167 |  | 
| 164 168 | 
             
                # Spawns a new actor.
         | 
| 165 169 | 
             
                #
         | 
| @@ -184,7 +188,7 @@ module Concurrent | |
| 184 188 | 
             
                  if Actress.current
         | 
| 185 189 | 
             
                    Core.new(spawn_optionify(*args).merge(parent: Actress.current), &block).reference
         | 
| 186 190 | 
             
                  else
         | 
| 187 | 
            -
                     | 
| 191 | 
            +
                    root.ask([:spawn, spawn_optionify(*args), block]).value
         | 
| 188 192 | 
             
                  end
         | 
| 189 193 | 
             
                end
         | 
| 190 194 |  | 
| @@ -17,7 +17,7 @@ module Concurrent | |
| 17 17 | 
             
                  #   @return [String] the name of this instance, it should be uniq (not enforced right now)
         | 
| 18 18 | 
             
                  # @!attribute [r] path
         | 
| 19 19 | 
             
                  #   @return [String] a path of this actor. It is used for easier orientation and logging.
         | 
| 20 | 
            -
                  #     Path is constructed recursively with: `parent.path + self.name` up to a {Actress | 
| 20 | 
            +
                  #     Path is constructed recursively with: `parent.path + self.name` up to a {Actress.root},
         | 
| 21 21 | 
             
                  #     e.g. `/an_actor/its_child`.
         | 
| 22 22 | 
             
                  #     (It will also probably form a supervision path (failures will be reported up to parents)
         | 
| 23 23 | 
             
                  #     in future versions.)
         | 
    
        data/lib/concurrent/async.rb
    CHANGED
    
    | @@ -3,8 +3,8 @@ require 'concurrent/configuration' | |
| 3 3 | 
             
            require 'concurrent/delay'
         | 
| 4 4 | 
             
            require 'concurrent/errors'
         | 
| 5 5 | 
             
            require 'concurrent/ivar'
         | 
| 6 | 
            -
            require 'concurrent/ | 
| 7 | 
            -
            require 'concurrent/executor/ | 
| 6 | 
            +
            require 'concurrent/executor/immediate_executor'
         | 
| 7 | 
            +
            require 'concurrent/executor/serialized_execution'
         | 
| 8 8 |  | 
| 9 9 | 
             
            module Concurrent
         | 
| 10 10 |  | 
| @@ -124,69 +124,24 @@ module Concurrent | |
| 124 124 | 
             
                end
         | 
| 125 125 | 
             
                module_function :validate_argc
         | 
| 126 126 |  | 
| 127 | 
            -
                # Delegates synchronous, thread-safe method calls to the wrapped object.
         | 
| 128 | 
            -
                #
         | 
| 129 | 
            -
                # @!visibility private
         | 
| 130 | 
            -
                class AwaitDelegator # :nodoc:
         | 
| 131 | 
            -
             | 
| 132 | 
            -
                  # Create a new delegator object wrapping the given `delegate` and
         | 
| 133 | 
            -
                  # protecting it with the given `mutex`.
         | 
| 134 | 
            -
                  #
         | 
| 135 | 
            -
                  # @param [Object] delegate the object to wrap and delegate method calls to
         | 
| 136 | 
            -
                  # @param [Mutex] mutex the mutex lock to use when delegating method calls
         | 
| 137 | 
            -
                  def initialize(delegate, mutex)
         | 
| 138 | 
            -
                    @delegate = delegate
         | 
| 139 | 
            -
                    @mutex = mutex
         | 
| 140 | 
            -
                  end
         | 
| 141 | 
            -
             | 
| 142 | 
            -
                  # Delegates method calls to the wrapped object. For performance,
         | 
| 143 | 
            -
                  # dynamically defines the given method on the delegator so that
         | 
| 144 | 
            -
                  # all future calls to `method` will not be directed here.
         | 
| 145 | 
            -
                  #
         | 
| 146 | 
            -
                  # @param [Symbol] method the method being called
         | 
| 147 | 
            -
                  # @param [Array] args zero or more arguments to the method
         | 
| 148 | 
            -
                  #
         | 
| 149 | 
            -
                  # @return [IVar] the result of the method call
         | 
| 150 | 
            -
                  #
         | 
| 151 | 
            -
                  # @raise [NameError] the object does not respond to `method` method
         | 
| 152 | 
            -
                  # @raise [ArgumentError] the given `args` do not match the arity of `method`
         | 
| 153 | 
            -
                  def method_missing(method, *args, &block)
         | 
| 154 | 
            -
                    super unless @delegate.respond_to?(method)
         | 
| 155 | 
            -
                    Async::validate_argc(@delegate, method, *args)
         | 
| 156 | 
            -
             | 
| 157 | 
            -
                    self.define_singleton_method(method) do |*args|
         | 
| 158 | 
            -
                      Async::validate_argc(@delegate, method, *args)
         | 
| 159 | 
            -
                      ivar = Concurrent::IVar.new
         | 
| 160 | 
            -
                      value, reason = nil, nil
         | 
| 161 | 
            -
                      begin
         | 
| 162 | 
            -
                        @mutex.synchronize do
         | 
| 163 | 
            -
                          value = @delegate.send(method, *args, &block)
         | 
| 164 | 
            -
                        end
         | 
| 165 | 
            -
                      rescue => reason
         | 
| 166 | 
            -
                        # caught
         | 
| 167 | 
            -
                      ensure
         | 
| 168 | 
            -
                        return ivar.complete(reason.nil?, value, reason)
         | 
| 169 | 
            -
                      end
         | 
| 170 | 
            -
                    end
         | 
| 171 | 
            -
             | 
| 172 | 
            -
                    self.send(method, *args)
         | 
| 173 | 
            -
                  end
         | 
| 174 | 
            -
                end
         | 
| 175 | 
            -
             | 
| 176 127 | 
             
                # Delegates asynchronous, thread-safe method calls to the wrapped object.
         | 
| 177 128 | 
             
                #
         | 
| 178 129 | 
             
                # @!visibility private
         | 
| 179 130 | 
             
                class AsyncDelegator # :nodoc:
         | 
| 180 131 |  | 
| 181 | 
            -
                  # Create a new delegator object wrapping the given  | 
| 182 | 
            -
                  # protecting it with the given  | 
| 132 | 
            +
                  # Create a new delegator object wrapping the given delegate,
         | 
| 133 | 
            +
                  # protecting it with the given serializer, and executing it on the
         | 
| 134 | 
            +
                  # given executor. Block if necessary.
         | 
| 183 135 | 
             
                  #
         | 
| 184 136 | 
             
                  # @param [Object] delegate the object to wrap and delegate method calls to
         | 
| 185 | 
            -
                  # @param [ | 
| 186 | 
            -
                   | 
| 137 | 
            +
                  # @param [Concurrent::Delay] executor a `Delay` wrapping the executor on which to execute delegated method calls
         | 
| 138 | 
            +
                  # @param [Concurrent::SerializedExecution] serializer the serializer to use when delegating method calls
         | 
| 139 | 
            +
                  # @param [Boolean] blocking will block awaiting result when `true`
         | 
| 140 | 
            +
                  def initialize(delegate, executor, serializer, blocking = false)
         | 
| 187 141 | 
             
                    @delegate = delegate
         | 
| 188 142 | 
             
                    @executor = executor
         | 
| 189 | 
            -
                    @ | 
| 143 | 
            +
                    @serializer = serializer
         | 
| 144 | 
            +
                    @blocking = blocking
         | 
| 190 145 | 
             
                  end
         | 
| 191 146 |  | 
| 192 147 | 
             
                  # Delegates method calls to the wrapped object. For performance,
         | 
| @@ -206,11 +161,19 @@ module Concurrent | |
| 206 161 |  | 
| 207 162 | 
             
                    self.define_singleton_method(method) do |*args|
         | 
| 208 163 | 
             
                      Async::validate_argc(@delegate, method, *args)
         | 
| 209 | 
            -
                      Concurrent:: | 
| 210 | 
            -
             | 
| 211 | 
            -
             | 
| 164 | 
            +
                      ivar = Concurrent::IVar.new
         | 
| 165 | 
            +
                      value, reason = nil, nil
         | 
| 166 | 
            +
                      @serializer.post(@executor.value) do
         | 
| 167 | 
            +
                        begin
         | 
| 168 | 
            +
                          value = @delegate.send(method, *args, &block)
         | 
| 169 | 
            +
                        rescue => reason
         | 
| 170 | 
            +
                          # caught
         | 
| 171 | 
            +
                        ensure
         | 
| 172 | 
            +
                          ivar.complete(reason.nil?, value, reason)
         | 
| 212 173 | 
             
                        end
         | 
| 213 174 | 
             
                      end
         | 
| 175 | 
            +
                      ivar.value if @blocking
         | 
| 176 | 
            +
                      ivar
         | 
| 214 177 | 
             
                    end
         | 
| 215 178 |  | 
| 216 179 | 
             
                    self.send(method, *args)
         | 
| @@ -219,9 +182,9 @@ module Concurrent | |
| 219 182 |  | 
| 220 183 | 
             
                # Causes the chained method call to be performed asynchronously on the
         | 
| 221 184 | 
             
                # global thread pool. The method called by this method will return a
         | 
| 222 | 
            -
                #  | 
| 185 | 
            +
                # future object in the `:pending` state and the method call will have
         | 
| 223 186 | 
             
                # been scheduled on the global thread pool. The final disposition of the
         | 
| 224 | 
            -
                # method call can be obtained by inspecting the returned  | 
| 187 | 
            +
                # method call can be obtained by inspecting the returned future.
         | 
| 225 188 | 
             
                #
         | 
| 226 189 | 
             
                # Before scheduling the method on the global thread pool a best-effort
         | 
| 227 190 | 
             
                # attempt will be made to validate that the method exists on the object
         | 
| @@ -238,15 +201,15 @@ module Concurrent | |
| 238 201 | 
             
                #   method call. Use *only* protected method calls when sharing the object
         | 
| 239 202 | 
             
                #   between threads.
         | 
| 240 203 | 
             
                #
         | 
| 241 | 
            -
                # @return [Concurrent:: | 
| 204 | 
            +
                # @return [Concurrent::IVar] the pending result of the asynchronous operation
         | 
| 242 205 | 
             
                #
         | 
| 243 206 | 
             
                # @raise [Concurrent::InitializationError] `#init_mutex` has not been called
         | 
| 244 207 | 
             
                # @raise [NameError] the object does not respond to `method` method
         | 
| 245 208 | 
             
                # @raise [ArgumentError] the given `args` do not match the arity of `method`
         | 
| 246 209 | 
             
                #
         | 
| 247 | 
            -
                # @see Concurrent:: | 
| 210 | 
            +
                # @see Concurrent::IVar
         | 
| 248 211 | 
             
                def async
         | 
| 249 | 
            -
                  raise InitializationError.new('#init_mutex was never called') unless @ | 
| 212 | 
            +
                  raise InitializationError.new('#init_mutex was never called') unless @__async_initialized__
         | 
| 250 213 | 
             
                  @__async_delegator__.value
         | 
| 251 214 | 
             
                end
         | 
| 252 215 | 
             
                alias_method :future, :async
         | 
| @@ -280,7 +243,7 @@ module Concurrent | |
| 280 243 | 
             
                #
         | 
| 281 244 | 
             
                # @see Concurrent::IVar
         | 
| 282 245 | 
             
                def await
         | 
| 283 | 
            -
                  raise InitializationError.new('#init_mutex was never called') unless @ | 
| 246 | 
            +
                  raise InitializationError.new('#init_mutex was never called') unless @__async_initialized__
         | 
| 284 247 | 
             
                  @__await_delegator__.value
         | 
| 285 248 | 
             
                end
         | 
| 286 249 | 
             
                alias_method :delay, :await
         | 
| @@ -290,12 +253,12 @@ module Concurrent | |
| 290 253 | 
             
                # @raise [Concurrent::InitializationError] `#init_mutex` has not been called
         | 
| 291 254 | 
             
                # @raise [ArgumentError] executor has already been set
         | 
| 292 255 | 
             
                def executor=(executor)
         | 
| 293 | 
            -
                  raise InitializationError.new('#init_mutex was never called') unless @ | 
| 294 | 
            -
                  @ | 
| 256 | 
            +
                  raise InitializationError.new('#init_mutex was never called') unless @__async_initialized__
         | 
| 257 | 
            +
                  @__async_executor__.reconfigure { executor } or
         | 
| 295 258 | 
             
                    raise ArgumentError.new('executor has already been set')
         | 
| 296 259 | 
             
                end
         | 
| 297 260 |  | 
| 298 | 
            -
                # Initialize the internal  | 
| 261 | 
            +
                # Initialize the internal serializer and other synchronization objects. This method
         | 
| 299 262 | 
             
                # *must* be called from the constructor of the including class or explicitly
         | 
| 300 263 | 
             
                # by the caller prior to calling any other methods. If `init_mutex` is *not*
         | 
| 301 264 | 
             
                # called explicitly the async/await/executor methods will raize a
         | 
| @@ -308,12 +271,14 @@ module Concurrent | |
| 308 271 | 
             
                #
         | 
| 309 272 | 
             
                # @raise [Concurrent::InitializationError] when called more than once
         | 
| 310 273 | 
             
                def init_mutex
         | 
| 311 | 
            -
                  raise InitializationError.new('#init_mutex was already called') if @ | 
| 312 | 
            -
                   | 
| 313 | 
            -
                   | 
| 314 | 
            -
                  @ | 
| 315 | 
            -
                  @ | 
| 316 | 
            -
             | 
| 274 | 
            +
                  raise InitializationError.new('#init_mutex was already called') if @__async_initialized__
         | 
| 275 | 
            +
                  @__async_initialized__ = true
         | 
| 276 | 
            +
                  serializer = Concurrent::SerializedExecution.new
         | 
| 277 | 
            +
                  @__async_executor__ = Delay.new{ Concurrent.configuration.global_operation_pool }
         | 
| 278 | 
            +
                  @__await_delegator__ = Delay.new{ AsyncDelegator.new(
         | 
| 279 | 
            +
                    self, Delay.new{ Concurrent::ImmediateExecutor.new }, serializer, true) }
         | 
| 280 | 
            +
                  @__async_delegator__ = Delay.new{ AsyncDelegator.new(
         | 
| 281 | 
            +
                    self, @__async_executor__, serializer, false) }
         | 
| 317 282 | 
             
                end
         | 
| 318 283 | 
             
              end
         | 
| 319 284 | 
             
            end
         | 
    
        data/lib/concurrent/atomic.rb
    CHANGED
    
    | @@ -16,30 +16,50 @@ end | |
| 16 16 |  | 
| 17 17 | 
             
            if defined? Concurrent::JavaAtomic
         | 
| 18 18 |  | 
| 19 | 
            +
              # @!macro [attach] atomic_reference
         | 
| 20 | 
            +
              #
         | 
| 21 | 
            +
              #   An object reference that may be updated atomically.
         | 
| 22 | 
            +
              #
         | 
| 23 | 
            +
              #   @since 0.7.0.rc0
         | 
| 24 | 
            +
              #   @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html
         | 
| 25 | 
            +
              #   @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html
         | 
| 19 26 | 
             
              class Concurrent::Atomic < Concurrent::JavaAtomic
         | 
| 20 27 | 
             
              end
         | 
| 21 28 |  | 
| 22 29 | 
             
            elsif defined? Concurrent::CAtomic
         | 
| 23 30 |  | 
| 31 | 
            +
              # @!macro [attach] concurrent_update_error
         | 
| 32 | 
            +
              #
         | 
| 33 | 
            +
              # This exception may be thrown by methods that have detected concurrent
         | 
| 34 | 
            +
              # modification of an object when such modification is not permissible.
         | 
| 24 35 | 
             
              class Concurrent::Atomic < Concurrent::CAtomic
         | 
| 25 36 | 
             
              end
         | 
| 26 37 |  | 
| 27 38 | 
             
            elsif defined? Concurrent::RbxAtomic
         | 
| 28 39 |  | 
| 40 | 
            +
              # @!macro atomic_reference
         | 
| 29 41 | 
             
              class Concurrent::Atomic < Concurrent::RbxAtomic
         | 
| 30 42 | 
             
              end
         | 
| 31 43 |  | 
| 32 44 | 
             
            else
         | 
| 33 45 |  | 
| 46 | 
            +
              # @!macro atomic_reference
         | 
| 34 47 | 
             
              class Concurrent::Atomic < Concurrent::MutexAtomic
         | 
| 35 48 | 
             
              end
         | 
| 36 49 | 
             
            end
         | 
| 37 50 |  | 
| 51 | 
            +
            # @!macro atomic_reference
         | 
| 38 52 | 
             
            class Atomic < Concurrent::Atomic
         | 
| 39 53 |  | 
| 54 | 
            +
              # @!macro concurrent_update_error
         | 
| 40 55 | 
             
              ConcurrentUpdateError = Class.new(Concurrent::ConcurrentUpdateError)
         | 
| 41 56 |  | 
| 42 | 
            -
               | 
| 57 | 
            +
              # @!macro [attach] atomic_reference_method_initialize
         | 
| 58 | 
            +
              #
         | 
| 59 | 
            +
              # Creates a new Atomic reference with null initial value.
         | 
| 60 | 
            +
              #
         | 
| 61 | 
            +
              # @param [Object] value the initial value
         | 
| 62 | 
            +
              def initialize(value)
         | 
| 43 63 | 
             
                warn "[DEPRECATED] Please use Concurrent::Atomic instead."
         | 
| 44 64 | 
             
                super
         | 
| 45 65 | 
             
              end
         | 
| @@ -4,14 +4,36 @@ module Concurrent | |
| 4 4 |  | 
| 5 5 | 
             
              # Define update methods that use direct paths
         | 
| 6 6 | 
             
              module AtomicDirectUpdate
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                # @!macro [attach] atomic_reference_method_update
         | 
| 9 | 
            +
                #
         | 
| 7 10 | 
             
                # Pass the current value to the given block, replacing it
         | 
| 8 11 | 
             
                # with the block's result. May retry if the value changes
         | 
| 9 12 | 
             
                # during the block's execution.
         | 
| 13 | 
            +
                # 
         | 
| 14 | 
            +
                # @yield [Object] Calculate a new value for the atomic reference using
         | 
| 15 | 
            +
                #   given (old) value
         | 
| 16 | 
            +
                # @yieldparam [Object] old_value the starting value of the atomic reference
         | 
| 17 | 
            +
                #
         | 
| 18 | 
            +
                # @return [Object] the new value
         | 
| 10 19 | 
             
                def update
         | 
| 11 20 | 
             
                  true until compare_and_set(old_value = get, new_value = yield(old_value))
         | 
| 12 21 | 
             
                  new_value
         | 
| 13 22 | 
             
                end
         | 
| 14 23 |  | 
| 24 | 
            +
                # @!macro [attach] atomic_reference_method_try_update
         | 
| 25 | 
            +
                #
         | 
| 26 | 
            +
                # Pass the current value to the given block, replacing it
         | 
| 27 | 
            +
                # with the block's result. Raise an exception if the update
         | 
| 28 | 
            +
                # fails.
         | 
| 29 | 
            +
                # 
         | 
| 30 | 
            +
                # @yield [Object] Calculate a new value for the atomic reference using
         | 
| 31 | 
            +
                #   given (old) value
         | 
| 32 | 
            +
                # @yieldparam [Object] old_value the starting value of the atomic reference
         | 
| 33 | 
            +
                #
         | 
| 34 | 
            +
                # @return [Object] the new value
         | 
| 35 | 
            +
                #
         | 
| 36 | 
            +
                # @raise [Concurrent::ConcurrentUpdateError] if the update fails
         | 
| 15 37 | 
             
                def try_update
         | 
| 16 38 | 
             
                  old_value = get
         | 
| 17 39 | 
             
                  new_value = yield old_value
         | 
| @@ -4,26 +4,46 @@ require 'concurrent/atomic_reference/numeric_cas_wrapper' | |
| 4 4 |  | 
| 5 5 | 
             
            module Concurrent
         | 
| 6 6 |  | 
| 7 | 
            -
              #  | 
| 8 | 
            -
              class MutexAtomic | 
| 7 | 
            +
              # @!macro atomic_reference
         | 
| 8 | 
            +
              class MutexAtomic
         | 
| 9 9 | 
             
                include Concurrent::AtomicDirectUpdate
         | 
| 10 10 | 
             
                include Concurrent::AtomicNumericCompareAndSetWrapper
         | 
| 11 11 |  | 
| 12 | 
            +
                # @!macro atomic_reference_method_initialize
         | 
| 12 13 | 
             
                def initialize(value = nil)
         | 
| 13 14 | 
             
                  @mutex = Mutex.new
         | 
| 14 15 | 
             
                  @value = value
         | 
| 15 16 | 
             
                end
         | 
| 16 17 |  | 
| 18 | 
            +
                # @!macro [attach] atomic_reference_method_get
         | 
| 19 | 
            +
                #
         | 
| 20 | 
            +
                #   Gets the current value.
         | 
| 21 | 
            +
                #
         | 
| 22 | 
            +
                #   @return [Object] the current value
         | 
| 17 23 | 
             
                def get
         | 
| 18 24 | 
             
                  @mutex.synchronize { @value }
         | 
| 19 25 | 
             
                end
         | 
| 20 | 
            -
                 | 
| 26 | 
            +
                alias_method :value, :get
         | 
| 21 27 |  | 
| 28 | 
            +
                # @!macro [attach] atomic_reference_method_set
         | 
| 29 | 
            +
                #
         | 
| 30 | 
            +
                #   Sets to the given value.
         | 
| 31 | 
            +
                #
         | 
| 32 | 
            +
                #   @param [Object] new_value the new value
         | 
| 33 | 
            +
                #
         | 
| 34 | 
            +
                #   @return [Object] the new value
         | 
| 22 35 | 
             
                def set(new_value)
         | 
| 23 36 | 
             
                  @mutex.synchronize { @value = new_value }
         | 
| 24 37 | 
             
                end
         | 
| 25 | 
            -
                 | 
| 38 | 
            +
                alias_method :value=, :set
         | 
| 26 39 |  | 
| 40 | 
            +
                # @!macro [attach] atomic_reference_method_get_and_set
         | 
| 41 | 
            +
                #
         | 
| 42 | 
            +
                #   Atomically sets to the given value and returns the old value.
         | 
| 43 | 
            +
                #
         | 
| 44 | 
            +
                #   @param [Object] new_value the new value
         | 
| 45 | 
            +
                #
         | 
| 46 | 
            +
                #   @return [Object] the old value
         | 
| 27 47 | 
             
                def get_and_set(new_value)
         | 
| 28 48 | 
             
                  @mutex.synchronize do
         | 
| 29 49 | 
             
                    old_value = @value
         | 
| @@ -31,9 +51,19 @@ module Concurrent | |
| 31 51 | 
             
                    old_value
         | 
| 32 52 | 
             
                  end
         | 
| 33 53 | 
             
                end
         | 
| 34 | 
            -
                 | 
| 54 | 
            +
                alias_method :swap, :get_and_set
         | 
| 35 55 |  | 
| 36 | 
            -
                 | 
| 56 | 
            +
                # @!macro [attach] atomic_reference_method_compare_and_set
         | 
| 57 | 
            +
                #
         | 
| 58 | 
            +
                #   Atomically sets the value to the given updated value if
         | 
| 59 | 
            +
                #   the current value == the expected value.
         | 
| 60 | 
            +
                #
         | 
| 61 | 
            +
                #   @param [Object] old_value the expected value
         | 
| 62 | 
            +
                #   @param [Object] new_value the new value
         | 
| 63 | 
            +
                #
         | 
| 64 | 
            +
                #   @return [Boolean] `true` if successful. A `false` return indicates
         | 
| 65 | 
            +
                #   that the actual value was not equal to the expected value.
         | 
| 66 | 
            +
                def _compare_and_set(old_value, new_value) #:nodoc:
         | 
| 37 67 | 
             
                  return false unless @mutex.try_lock
         | 
| 38 68 | 
             
                  begin
         | 
| 39 69 | 
             
                    return false unless @value.equal? old_value
         |