concurrent-ruby 1.0.0.pre4-java → 1.0.0.pre5-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.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +11 -1
 - data/lib/concurrent/agent.rb +5 -1
 - data/lib/concurrent/async.rb +77 -38
 - data/lib/concurrent/atom.rb +2 -1
 - data/lib/concurrent/atomic/atomic_boolean.rb +1 -1
 - data/lib/concurrent/atomic/atomic_fixnum.rb +1 -1
 - data/lib/concurrent/atomic/atomic_reference.rb +1 -1
 - data/lib/concurrent/atomic/semaphore.rb +1 -1
 - data/lib/concurrent/atomic_reference/jruby+truffle.rb +1 -0
 - data/lib/concurrent/atomic_reference/jruby.rb +1 -1
 - data/lib/concurrent/atomic_reference/ruby.rb +1 -1
 - data/lib/concurrent/concern/dereferenceable.rb +9 -24
 - data/lib/concurrent/concern/obligation.rb +11 -8
 - data/lib/concurrent/delay.rb +1 -1
 - data/lib/concurrent/exchanger.rb +30 -17
 - data/lib/concurrent/executor/ruby_thread_pool_executor.rb +6 -1
 - data/lib/concurrent/ivar.rb +1 -1
 - data/lib/concurrent/lazy_register.rb +11 -8
 - data/lib/concurrent/map.rb +1 -1
 - data/lib/concurrent/maybe.rb +6 -3
 - data/lib/concurrent/mvar.rb +26 -2
 - data/lib/concurrent/promise.rb +1 -1
 - data/lib/concurrent/synchronization.rb +3 -0
 - data/lib/concurrent/synchronization/abstract_lockable_object.rb +1 -20
 - data/lib/concurrent/synchronization/abstract_object.rb +1 -27
 - data/lib/concurrent/synchronization/jruby_object.rb +26 -18
 - data/lib/concurrent/synchronization/lockable_object.rb +29 -16
 - data/lib/concurrent/synchronization/mri_object.rb +27 -19
 - data/lib/concurrent/synchronization/object.rb +48 -53
 - data/lib/concurrent/synchronization/rbx_lockable_object.rb +9 -8
 - data/lib/concurrent/synchronization/rbx_object.rb +29 -21
 - data/lib/concurrent/synchronization/volatile.rb +34 -0
 - data/lib/concurrent/timer_task.rb +0 -1
 - data/lib/concurrent/tvar.rb +3 -1
 - data/lib/concurrent/utility/engine.rb +4 -0
 - data/lib/concurrent/utility/native_extension_loader.rb +6 -3
 - data/lib/concurrent/version.rb +2 -2
 - data/lib/concurrent_ruby_ext.jar +0 -0
 - metadata +7 -5
 
    
        data/lib/concurrent/delay.rb
    CHANGED
    
    
    
        data/lib/concurrent/exchanger.rb
    CHANGED
    
    | 
         @@ -38,7 +38,7 @@ module Concurrent 
     | 
|
| 
       38 
38 
     | 
    
         
             
              #     threads.each {|t| t.join(2) }
         
     | 
| 
       39 
39 
     | 
    
         
             
              #
         
     | 
| 
       40 
40 
     | 
    
         
             
              # @!visibility private
         
     | 
| 
       41 
     | 
    
         
            -
              class AbstractExchanger
         
     | 
| 
      
 41 
     | 
    
         
            +
              class AbstractExchanger < Synchronization::Object
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
43 
     | 
    
         
             
                # @!visibility private
         
     | 
| 
       44 
44 
     | 
    
         
             
                CANCEL = Object.new
         
     | 
| 
         @@ -46,7 +46,7 @@ module Concurrent 
     | 
|
| 
       46 
46 
     | 
    
         | 
| 
       47 
47 
     | 
    
         
             
                # @!macro [attach] exchanger_method_initialize
         
     | 
| 
       48 
48 
     | 
    
         
             
                def initialize
         
     | 
| 
       49 
     | 
    
         
            -
                   
     | 
| 
      
 49 
     | 
    
         
            +
                  super
         
     | 
| 
       50 
50 
     | 
    
         
             
                end
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
       52 
52 
     | 
    
         
             
                # @!macro [attach] exchanger_method_do_exchange
         
     | 
| 
         @@ -140,24 +140,38 @@ module Concurrent 
     | 
|
| 
       140 
140 
     | 
    
         
             
                # not include the arena or the multi-processor spin loops.
         
     | 
| 
       141 
141 
     | 
    
         
             
                # http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/Exchanger.java
         
     | 
| 
       142 
142 
     | 
    
         | 
| 
       143 
     | 
    
         
            -
                 
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
      
 143 
     | 
    
         
            +
                safe_initialization!
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                class Node < Concurrent::Synchronization::Object
         
     | 
| 
      
 146 
     | 
    
         
            +
                  attr_volatile_with_cas :value
         
     | 
| 
      
 147 
     | 
    
         
            +
                  safe_initialization!
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
       146 
149 
     | 
    
         
             
                  def initialize(item)
         
     | 
| 
       147 
     | 
    
         
            -
                     
     | 
| 
       148 
     | 
    
         
            -
                    @ 
     | 
| 
       149 
     | 
    
         
            -
                     
     | 
| 
      
 150 
     | 
    
         
            +
                    super()
         
     | 
| 
      
 151 
     | 
    
         
            +
                    @Item = item
         
     | 
| 
      
 152 
     | 
    
         
            +
                    @Latch = Concurrent::CountDownLatch.new
         
     | 
| 
      
 153 
     | 
    
         
            +
                    self.value = nil
         
     | 
| 
      
 154 
     | 
    
         
            +
                  end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                  def latch
         
     | 
| 
      
 157 
     | 
    
         
            +
                    @Latch
         
     | 
| 
      
 158 
     | 
    
         
            +
                  end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                  def item
         
     | 
| 
      
 161 
     | 
    
         
            +
                    @Item
         
     | 
| 
       150 
162 
     | 
    
         
             
                  end
         
     | 
| 
       151 
163 
     | 
    
         
             
                end
         
     | 
| 
       152 
164 
     | 
    
         
             
                private_constant :Node
         
     | 
| 
       153 
165 
     | 
    
         | 
| 
       154 
166 
     | 
    
         
             
                # @!macro exchanger_method_initialize
         
     | 
| 
       155 
167 
     | 
    
         
             
                def initialize
         
     | 
| 
       156 
     | 
    
         
            -
                   
     | 
| 
      
 168 
     | 
    
         
            +
                  super
         
     | 
| 
       157 
169 
     | 
    
         
             
                end
         
     | 
| 
       158 
170 
     | 
    
         | 
| 
       159 
171 
     | 
    
         
             
                private
         
     | 
| 
       160 
172 
     | 
    
         | 
| 
      
 173 
     | 
    
         
            +
                attr_volatile_with_cas(:slot)
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
       161 
175 
     | 
    
         
             
                # @!macro exchanger_method_do_exchange
         
     | 
| 
       162 
176 
     | 
    
         
             
                #
         
     | 
| 
       163 
177 
     | 
    
         
             
                # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout
         
     | 
| 
         @@ -247,20 +261,19 @@ module Concurrent 
     | 
|
| 
       247 
261 
     | 
    
         
             
                  #     - Return the occupier's item
         
     | 
| 
       248 
262 
     | 
    
         | 
| 
       249 
263 
     | 
    
         
             
                  value = NULL if value.nil?                        # The sentinel allows nil to be a valid value
         
     | 
| 
       250 
     | 
    
         
            -
                  slot = @slot                                      # Convenience to minimize typing @
         
     | 
| 
       251 
264 
     | 
    
         
             
                  me = Node.new(value)                              # create my node in case I need to occupy
         
     | 
| 
       252 
265 
     | 
    
         
             
                  end_at = Concurrent.monotonic_time + timeout.to_f # The time to give up
         
     | 
| 
       253 
266 
     | 
    
         | 
| 
       254 
267 
     | 
    
         
             
                  result = loop do
         
     | 
| 
       255 
     | 
    
         
            -
                    other = slot 
     | 
| 
       256 
     | 
    
         
            -
                    if other &&  
     | 
| 
      
 268 
     | 
    
         
            +
                    other = slot
         
     | 
| 
      
 269 
     | 
    
         
            +
                    if other && compare_and_set_slot(other, nil)
         
     | 
| 
       257 
270 
     | 
    
         
             
                      # try to fulfill
         
     | 
| 
       258 
     | 
    
         
            -
                      if other. 
     | 
| 
      
 271 
     | 
    
         
            +
                      if other.compare_and_set_value(nil, value)
         
     | 
| 
       259 
272 
     | 
    
         
             
                        # happy path
         
     | 
| 
       260 
273 
     | 
    
         
             
                        other.latch.count_down
         
     | 
| 
       261 
274 
     | 
    
         
             
                        break other.item
         
     | 
| 
       262 
275 
     | 
    
         
             
                      end
         
     | 
| 
       263 
     | 
    
         
            -
                    elsif other.nil? &&  
     | 
| 
      
 276 
     | 
    
         
            +
                    elsif other.nil? && compare_and_set_slot(nil, me)
         
     | 
| 
       264 
277 
     | 
    
         
             
                      # try to occupy
         
     | 
| 
       265 
278 
     | 
    
         
             
                      timeout = end_at - Concurrent.monotonic_time if timeout
         
     | 
| 
       266 
279 
     | 
    
         
             
                      if me.latch.wait(timeout)
         
     | 
| 
         @@ -268,11 +281,11 @@ module Concurrent 
     | 
|
| 
       268 
281 
     | 
    
         
             
                        break me.value
         
     | 
| 
       269 
282 
     | 
    
         
             
                      else
         
     | 
| 
       270 
283 
     | 
    
         
             
                        # attempt to remove myself from the slot
         
     | 
| 
       271 
     | 
    
         
            -
                        if  
     | 
| 
      
 284 
     | 
    
         
            +
                        if compare_and_set_slot(me, nil)
         
     | 
| 
       272 
285 
     | 
    
         
             
                          break CANCEL
         
     | 
| 
       273 
     | 
    
         
            -
                        elsif !me. 
     | 
| 
      
 286 
     | 
    
         
            +
                        elsif !me.compare_and_set_value(nil, CANCEL)
         
     | 
| 
       274 
287 
     | 
    
         
             
                          # I've failed to block the fulfiller
         
     | 
| 
       275 
     | 
    
         
            -
                          break me. 
     | 
| 
      
 288 
     | 
    
         
            +
                          break me.value
         
     | 
| 
       276 
289 
     | 
    
         
             
                        end
         
     | 
| 
       277 
290 
     | 
    
         
             
                      end
         
     | 
| 
       278 
291 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -101,6 +101,11 @@ module Concurrent 
     | 
|
| 
       101 
101 
     | 
    
         
             
                  synchronize { ns_worker_died worker }
         
     | 
| 
       102 
102 
     | 
    
         
             
                end
         
     | 
| 
       103 
103 
     | 
    
         | 
| 
      
 104 
     | 
    
         
            +
                # @!visibility private
         
     | 
| 
      
 105 
     | 
    
         
            +
                def worker_task_completed
         
     | 
| 
      
 106 
     | 
    
         
            +
                  synchronize { @completed_task_count += 1 }
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
       104 
109 
     | 
    
         
             
                private
         
     | 
| 
       105 
110 
     | 
    
         | 
| 
       106 
111 
     | 
    
         
             
                # @!visibility private
         
     | 
| 
         @@ -180,7 +185,6 @@ module Concurrent 
     | 
|
| 
       180 
185 
     | 
    
         
             
                  worker = (@ready.pop if @pool.size >= @min_length) || ns_add_busy_worker
         
     | 
| 
       181 
186 
     | 
    
         
             
                  if worker
         
     | 
| 
       182 
187 
     | 
    
         
             
                    worker << [task, args]
         
     | 
| 
       183 
     | 
    
         
            -
                    @completed_task_count += 1
         
     | 
| 
       184 
188 
     | 
    
         
             
                    true
         
     | 
| 
       185 
189 
     | 
    
         
             
                  else
         
     | 
| 
       186 
190 
     | 
    
         
             
                    false
         
     | 
| 
         @@ -327,6 +331,7 @@ module Concurrent 
     | 
|
| 
       327 
331 
     | 
    
         | 
| 
       328 
332 
     | 
    
         
             
                  def run_task(pool, task, args)
         
     | 
| 
       329 
333 
     | 
    
         
             
                    task.call(*args)
         
     | 
| 
      
 334 
     | 
    
         
            +
                    pool.worker_task_completed
         
     | 
| 
       330 
335 
     | 
    
         
             
                  rescue => ex
         
     | 
| 
       331 
336 
     | 
    
         
             
                    # let it fail
         
     | 
| 
       332 
337 
     | 
    
         
             
                    log DEBUG, ex
         
     | 
    
        data/lib/concurrent/ivar.rb
    CHANGED
    
    
| 
         @@ -7,19 +7,22 @@ module Concurrent 
     | 
|
| 
       7 
7 
     | 
    
         
             
              #
         
     | 
| 
       8 
8 
     | 
    
         
             
              # @example
         
     | 
| 
       9 
9 
     | 
    
         
             
              #   register = Concurrent::LazyRegister.new
         
     | 
| 
       10 
     | 
    
         
            -
              #   #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @ 
     | 
| 
      
 10 
     | 
    
         
            +
              #   #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @Data=#<Concurrent::AtomicReference:0x007fd7ecd5e1e0>>
         
     | 
| 
       11 
11 
     | 
    
         
             
              #   register[:key]
         
     | 
| 
       12 
12 
     | 
    
         
             
              #   #=> nil
         
     | 
| 
       13 
13 
     | 
    
         
             
              #   register.add(:key) { Concurrent::Actor.spawn!(Actor::AdHoc, :ping) { -> message { message } } }
         
     | 
| 
       14 
     | 
    
         
            -
              #   #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @ 
     | 
| 
      
 14 
     | 
    
         
            +
              #   #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @Data=#<Concurrent::AtomicReference:0x007fd7ecd5e1e0>>
         
     | 
| 
       15 
15 
     | 
    
         
             
              #   register[:key]
         
     | 
| 
       16 
16 
     | 
    
         
             
              #   #=> #<Concurrent::Actor::Reference /ping (Concurrent::Actor::AdHoc)>
         
     | 
| 
       17 
17 
     | 
    
         
             
              #
         
     | 
| 
       18 
18 
     | 
    
         
             
              # @!macro edge_warning
         
     | 
| 
       19 
     | 
    
         
            -
              class LazyRegister
         
     | 
| 
      
 19 
     | 
    
         
            +
              class LazyRegister < Synchronization::Object
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                private(*attr_volatile_with_cas(:data))
         
     | 
| 
       20 
22 
     | 
    
         | 
| 
       21 
23 
     | 
    
         
             
                def initialize
         
     | 
| 
       22 
     | 
    
         
            -
                   
     | 
| 
      
 24 
     | 
    
         
            +
                  super
         
     | 
| 
      
 25 
     | 
    
         
            +
                  self.data = {}
         
     | 
| 
       23 
26 
     | 
    
         
             
                end
         
     | 
| 
       24 
27 
     | 
    
         | 
| 
       25 
28 
     | 
    
         
             
                # Element reference. Retrieves the value object corresponding to the
         
     | 
| 
         @@ -31,7 +34,7 @@ module Concurrent 
     | 
|
| 
       31 
34 
     | 
    
         
             
                #
         
     | 
| 
       32 
35 
     | 
    
         
             
                # @raise Exception when the initialization block fails
         
     | 
| 
       33 
36 
     | 
    
         
             
                def [](key)
         
     | 
| 
       34 
     | 
    
         
            -
                  delay =  
     | 
| 
      
 37 
     | 
    
         
            +
                  delay = data[key]
         
     | 
| 
       35 
38 
     | 
    
         
             
                  delay ? delay.value! : nil
         
     | 
| 
       36 
39 
     | 
    
         
             
                end
         
     | 
| 
       37 
40 
     | 
    
         | 
| 
         @@ -40,7 +43,7 @@ module Concurrent 
     | 
|
| 
       40 
43 
     | 
    
         
             
                # @param [Object] key
         
     | 
| 
       41 
44 
     | 
    
         
             
                # @return [true, false] if the key is registered
         
     | 
| 
       42 
45 
     | 
    
         
             
                def registered?(key)
         
     | 
| 
       43 
     | 
    
         
            -
                   
     | 
| 
      
 46 
     | 
    
         
            +
                  data.key?(key)
         
     | 
| 
       44 
47 
     | 
    
         
             
                end
         
     | 
| 
       45 
48 
     | 
    
         | 
| 
       46 
49 
     | 
    
         
             
                alias_method :key?, :registered?
         
     | 
| 
         @@ -55,7 +58,7 @@ module Concurrent 
     | 
|
| 
       55 
58 
     | 
    
         
             
                # @return [LazyRegister] self
         
     | 
| 
       56 
59 
     | 
    
         
             
                def register(key, &block)
         
     | 
| 
       57 
60 
     | 
    
         
             
                  delay = Delay.new(executor: :immediate, &block)
         
     | 
| 
       58 
     | 
    
         
            -
                   
     | 
| 
      
 61 
     | 
    
         
            +
                  update_data { |h| h.merge(key => delay) }
         
     | 
| 
       59 
62 
     | 
    
         
             
                  self
         
     | 
| 
       60 
63 
     | 
    
         
             
                end
         
     | 
| 
       61 
64 
     | 
    
         | 
| 
         @@ -68,7 +71,7 @@ module Concurrent 
     | 
|
| 
       68 
71 
     | 
    
         
             
                #
         
     | 
| 
       69 
72 
     | 
    
         
             
                # @return [LazyRegister] self
         
     | 
| 
       70 
73 
     | 
    
         
             
                def unregister(key)
         
     | 
| 
       71 
     | 
    
         
            -
                   
     | 
| 
      
 74 
     | 
    
         
            +
                  update_data { |h| h.dup.tap { |j| j.delete(key) } }
         
     | 
| 
       72 
75 
     | 
    
         
             
                  self
         
     | 
| 
       73 
76 
     | 
    
         
             
                end
         
     | 
| 
       74 
77 
     | 
    
         | 
    
        data/lib/concurrent/map.rb
    CHANGED
    
    
    
        data/lib/concurrent/maybe.rb
    CHANGED
    
    | 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'concurrent/synchronization'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            module Concurrent
         
     | 
| 
       2 
4 
     | 
    
         | 
| 
       3 
5 
     | 
    
         
             
              # A `Maybe` encapsulates an optional value. A `Maybe` either contains a value
         
     | 
| 
         @@ -99,8 +101,9 @@ module Concurrent 
     | 
|
| 
       99 
101 
     | 
    
         
             
              #
         
     | 
| 
       100 
102 
     | 
    
         
             
              # @see https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html Haskell Data.Maybe
         
     | 
| 
       101 
103 
     | 
    
         
             
              # @see https://github.com/purescript/purescript-maybe/blob/master/docs/Data.Maybe.md PureScript Data.Maybe
         
     | 
| 
       102 
     | 
    
         
            -
              class Maybe
         
     | 
| 
      
 104 
     | 
    
         
            +
              class Maybe < Synchronization::Object
         
     | 
| 
       103 
105 
     | 
    
         
             
                include Comparable
         
     | 
| 
      
 106 
     | 
    
         
            +
                safe_initialization!
         
     | 
| 
       104 
107 
     | 
    
         | 
| 
       105 
108 
     | 
    
         
             
                # Indicates that the given attribute has not been set.
         
     | 
| 
       106 
109 
     | 
    
         
             
                # When `Just` the {#nothing} getter will return `NONE`.
         
     | 
| 
         @@ -168,7 +171,7 @@ module Concurrent 
     | 
|
| 
       168 
171 
     | 
    
         
             
                end
         
     | 
| 
       169 
172 
     | 
    
         | 
| 
       170 
173 
     | 
    
         
             
                # Is this `Maybe` a `Just` (successfully fulfilled with a value)?
         
     | 
| 
       171 
     | 
    
         
            -
                # 
     | 
| 
      
 174 
     | 
    
         
            +
                #
         
     | 
| 
       172 
175 
     | 
    
         
             
                # @return [Boolean] True if `Just` or false if `Nothing`.
         
     | 
| 
       173 
176 
     | 
    
         
             
                def just?
         
     | 
| 
       174 
177 
     | 
    
         
             
                  ! nothing?
         
     | 
| 
         @@ -176,7 +179,7 @@ module Concurrent 
     | 
|
| 
       176 
179 
     | 
    
         
             
                alias :fulfilled? :just?
         
     | 
| 
       177 
180 
     | 
    
         | 
| 
       178 
181 
     | 
    
         
             
                # Is this `Maybe` a `nothing` (rejected with an exception upon fulfillment)?
         
     | 
| 
       179 
     | 
    
         
            -
                # 
     | 
| 
      
 182 
     | 
    
         
            +
                #
         
     | 
| 
       180 
183 
     | 
    
         
             
                # @return [Boolean] True if `Nothing` or false if `Just`.
         
     | 
| 
       181 
184 
     | 
    
         
             
                def nothing?
         
     | 
| 
       182 
185 
     | 
    
         
             
                  @nothing != NONE
         
     | 
    
        data/lib/concurrent/mvar.rb
    CHANGED
    
    | 
         @@ -1,4 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'concurrent/concern/dereferenceable'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'concurrent/synchronization'
         
     | 
| 
       2 
3 
     | 
    
         | 
| 
       3 
4 
     | 
    
         
             
            module Concurrent
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
         @@ -34,9 +35,9 @@ module Concurrent 
     | 
|
| 
       34 
35 
     | 
    
         
             
              # 2. S. Peyton Jones, A. Gordon, and S. Finne. [Concurrent Haskell](http://dl.acm.org/citation.cfm?id=237794).
         
     | 
| 
       35 
36 
     | 
    
         
             
              #    In Proceedings of the 23rd Symposium on Principles of Programming Languages
         
     | 
| 
       36 
37 
     | 
    
         
             
              #    (PoPL), 1996.
         
     | 
| 
       37 
     | 
    
         
            -
              class MVar
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
              class MVar < Synchronization::Object
         
     | 
| 
       39 
39 
     | 
    
         
             
                include Concern::Dereferenceable
         
     | 
| 
      
 40 
     | 
    
         
            +
                safe_initialization!
         
     | 
| 
       40 
41 
     | 
    
         | 
| 
       41 
42 
     | 
    
         
             
                # Unique value that represents that an `MVar` was empty
         
     | 
| 
       42 
43 
     | 
    
         
             
                EMPTY = Object.new
         
     | 
| 
         @@ -78,6 +79,23 @@ module Concurrent 
     | 
|
| 
       78 
79 
     | 
    
         
             
                  end
         
     | 
| 
       79 
80 
     | 
    
         
             
                end
         
     | 
| 
       80 
81 
     | 
    
         | 
| 
      
 82 
     | 
    
         
            +
                # acquires lock on the from an `MVAR`, yields the value to provided block,
         
     | 
| 
      
 83 
     | 
    
         
            +
                # and release lock. A timeout can be set to limit the time spent blocked,
         
     | 
| 
      
 84 
     | 
    
         
            +
                # in which case it returns `TIMEOUT` if the time is exceeded.
         
     | 
| 
      
 85 
     | 
    
         
            +
                # @return [Object] the value returned by the block, or `TIMEOUT`
         
     | 
| 
      
 86 
     | 
    
         
            +
                def borrow(timeout = nil)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  @mutex.synchronize do
         
     | 
| 
      
 88 
     | 
    
         
            +
                    wait_for_full(timeout)
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                    # if we timeoud out we'll still be empty
         
     | 
| 
      
 91 
     | 
    
         
            +
                    if unlocked_full?
         
     | 
| 
      
 92 
     | 
    
         
            +
                      yield @value
         
     | 
| 
      
 93 
     | 
    
         
            +
                    else
         
     | 
| 
      
 94 
     | 
    
         
            +
                      TIMEOUT
         
     | 
| 
      
 95 
     | 
    
         
            +
                    end
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
       81 
99 
     | 
    
         
             
                # Put a value into an `MVar`, blocking if there is already a value until
         
     | 
| 
       82 
100 
     | 
    
         
             
                # it is empty. A timeout can be set to limit the time spent blocked, in
         
     | 
| 
       83 
101 
     | 
    
         
             
                # which case it returns `TIMEOUT` if the time is exceeded.
         
     | 
| 
         @@ -183,6 +201,12 @@ module Concurrent 
     | 
|
| 
       183 
201 
     | 
    
         
             
                  !empty?
         
     | 
| 
       184 
202 
     | 
    
         
             
                end
         
     | 
| 
       185 
203 
     | 
    
         | 
| 
      
 204 
     | 
    
         
            +
                protected
         
     | 
| 
      
 205 
     | 
    
         
            +
             
     | 
| 
      
 206 
     | 
    
         
            +
                def synchronize(&block)
         
     | 
| 
      
 207 
     | 
    
         
            +
                  @mutex.synchronize(&block)
         
     | 
| 
      
 208 
     | 
    
         
            +
                end
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
       186 
210 
     | 
    
         
             
                private
         
     | 
| 
       187 
211 
     | 
    
         | 
| 
       188 
212 
     | 
    
         
             
                def unlocked_empty?
         
     | 
    
        data/lib/concurrent/promise.rb
    CHANGED
    
    | 
         @@ -304,7 +304,7 @@ module Concurrent 
     | 
|
| 
       304 
304 
     | 
    
         
             
                # @return [Promise] the new promise
         
     | 
| 
       305 
305 
     | 
    
         
             
                def then(rescuer = nil, &block)
         
     | 
| 
       306 
306 
     | 
    
         
             
                  raise ArgumentError.new('rescuers and block are both missing') if rescuer.nil? && !block_given?
         
     | 
| 
       307 
     | 
    
         
            -
                  block = Proc.new { |result| result }  
     | 
| 
      
 307 
     | 
    
         
            +
                  block = Proc.new { |result| result } unless block_given?
         
     | 
| 
       308 
308 
     | 
    
         
             
                  child = Promise.new(
         
     | 
| 
       309 
309 
     | 
    
         
             
                    parent: self,
         
     | 
| 
       310 
310 
     | 
    
         
             
                    executor: @executor,
         
     | 
| 
         @@ -2,11 +2,13 @@ require 'concurrent/utility/engine' 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'concurrent/synchronization/abstract_object'
         
     | 
| 
       4 
4 
     | 
    
         
             
            require 'concurrent/utility/native_extension_loader' # load native parts first
         
     | 
| 
      
 5 
     | 
    
         
            +
            Concurrent.load_native_extensions
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
       6 
7 
     | 
    
         
             
            require 'concurrent/synchronization/mri_object'
         
     | 
| 
       7 
8 
     | 
    
         
             
            require 'concurrent/synchronization/jruby_object'
         
     | 
| 
       8 
9 
     | 
    
         
             
            require 'concurrent/synchronization/rbx_object'
         
     | 
| 
       9 
10 
     | 
    
         
             
            require 'concurrent/synchronization/object'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'concurrent/synchronization/volatile'
         
     | 
| 
       10 
12 
     | 
    
         | 
| 
       11 
13 
     | 
    
         
             
            require 'concurrent/synchronization/abstract_lockable_object'
         
     | 
| 
       12 
14 
     | 
    
         
             
            require 'concurrent/synchronization/mri_lockable_object'
         
     | 
| 
         @@ -20,6 +22,7 @@ require 'concurrent/synchronization/lock' 
     | 
|
| 
       20 
22 
     | 
    
         | 
| 
       21 
23 
     | 
    
         
             
            module Concurrent
         
     | 
| 
       22 
24 
     | 
    
         
             
              # {include:file:doc/synchronization.md}
         
     | 
| 
      
 25 
     | 
    
         
            +
              # {include:file:doc/synchronization-notes.md}
         
     | 
| 
       23 
26 
     | 
    
         
             
              module Synchronization
         
     | 
| 
       24 
27 
     | 
    
         
             
              end
         
     | 
| 
       25 
28 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Concurrent
         
     | 
| 
       2 
2 
     | 
    
         
             
              module Synchronization
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
       4 
4 
     | 
    
         
             
                # @!visibility private
         
     | 
| 
       5 
5 
     | 
    
         
             
                class AbstractLockableObject < Object
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
         @@ -15,25 +15,6 @@ module Concurrent 
     | 
|
| 
       15 
15 
     | 
    
         
             
                    raise NotImplementedError
         
     | 
| 
       16 
16 
     | 
    
         
             
                  end
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                  # @!macro [attach] synchronization_object_method_ns_initialize
         
     | 
| 
       19 
     | 
    
         
            -
                  #
         
     | 
| 
       20 
     | 
    
         
            -
                  #   initialization of the object called inside synchronize block
         
     | 
| 
       21 
     | 
    
         
            -
                  #   @note has to be called manually when required in children of this class
         
     | 
| 
       22 
     | 
    
         
            -
                  #   @example
         
     | 
| 
       23 
     | 
    
         
            -
                  #     class Child < Concurrent::Synchornization::Object
         
     | 
| 
       24 
     | 
    
         
            -
                  #       def initialize(*args, &block)
         
     | 
| 
       25 
     | 
    
         
            -
                  #         super(&nil)
         
     | 
| 
       26 
     | 
    
         
            -
                  #         synchronize { ns_initialize(*args, &block) }
         
     | 
| 
       27 
     | 
    
         
            -
                  #       end
         
     | 
| 
       28 
     | 
    
         
            -
                  #
         
     | 
| 
       29 
     | 
    
         
            -
                  #       def ns_initialize(*args, &block)
         
     | 
| 
       30 
     | 
    
         
            -
                  #         @args = args
         
     | 
| 
       31 
     | 
    
         
            -
                  #       end
         
     | 
| 
       32 
     | 
    
         
            -
                  #     end
         
     | 
| 
       33 
     | 
    
         
            -
                  # TODO (pitr 12-Sep-2015): remove
         
     | 
| 
       34 
     | 
    
         
            -
                  def ns_initialize(*args, &block)
         
     | 
| 
       35 
     | 
    
         
            -
                  end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
18 
     | 
    
         
             
                  # @!macro [attach] synchronization_object_method_ns_wait_until
         
     | 
| 
       38 
19 
     | 
    
         
             
                  #
         
     | 
| 
       39 
20 
     | 
    
         
             
                  #   Wait until condition is met or timeout passes,
         
     | 
| 
         @@ -1,8 +1,8 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Concurrent
         
     | 
| 
       2 
2 
     | 
    
         
             
              module Synchronization
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
                # @!macro synchronization_object
         
     | 
| 
       5 
4 
     | 
    
         
             
                # @!visibility private
         
     | 
| 
      
 5 
     | 
    
         
            +
                # @!macro internal_implementation_note
         
     | 
| 
       6 
6 
     | 
    
         
             
                class AbstractObject
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
                  # @abstract has to be implemented based on Ruby runtime
         
     | 
| 
         @@ -10,38 +10,12 @@ module Concurrent 
     | 
|
| 
       10 
10 
     | 
    
         
             
                    raise NotImplementedError
         
     | 
| 
       11 
11 
     | 
    
         
             
                  end
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                  # @!macro [attach] synchronization_object_method_ensure_ivar_visibility
         
     | 
| 
       14 
     | 
    
         
            -
                  #
         
     | 
| 
       15 
     | 
    
         
            -
                  #   Allows to construct immutable objects where all fields are visible after initialization, not requiring
         
     | 
| 
       16 
     | 
    
         
            -
                  #   further synchronization on access.
         
     | 
| 
       17 
     | 
    
         
            -
                  #   @example
         
     | 
| 
       18 
     | 
    
         
            -
                  #     class AClass
         
     | 
| 
       19 
     | 
    
         
            -
                  #       attr_reader :val
         
     | 
| 
       20 
     | 
    
         
            -
                  #       def initialize(val)
         
     | 
| 
       21 
     | 
    
         
            -
                  #         @val = val # final value, after assignment it's not changed (just convention, not enforced)
         
     | 
| 
       22 
     | 
    
         
            -
                  #         ensure_ivar_visibility!
         
     | 
| 
       23 
     | 
    
         
            -
                  #         # now it can be shared as Java's final field
         
     | 
| 
       24 
     | 
    
         
            -
                  #       end
         
     | 
| 
       25 
     | 
    
         
            -
                  #     end
         
     | 
| 
       26 
     | 
    
         
            -
                  # @!visibility private
         
     | 
| 
       27 
     | 
    
         
            -
                  def ensure_ivar_visibility!
         
     | 
| 
       28 
     | 
    
         
            -
                    # We have to prevent ivar writes to reordered with storing of the final instance reference
         
     | 
| 
       29 
     | 
    
         
            -
                    # Therefore wee need a fullFence to prevent reordering in both directions.
         
     | 
| 
       30 
     | 
    
         
            -
                    full_memory_barrier
         
     | 
| 
       31 
     | 
    
         
            -
                  end
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                  protected
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
13 
     | 
    
         
             
                  # @!visibility private
         
     | 
| 
       36 
14 
     | 
    
         
             
                  # @abstract
         
     | 
| 
       37 
15 
     | 
    
         
             
                  def full_memory_barrier
         
     | 
| 
       38 
16 
     | 
    
         
             
                    raise NotImplementedError
         
     | 
| 
       39 
17 
     | 
    
         
             
                  end
         
     | 
| 
       40 
18 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                  # @!macro [attach] synchronization_object_method_self_attr_volatile
         
     | 
| 
       42 
     | 
    
         
            -
                  #
         
     | 
| 
       43 
     | 
    
         
            -
                  #   creates methods for reading and writing to a instance variable with volatile (Java semantic) instance variable
         
     | 
| 
       44 
     | 
    
         
            -
                  #   return [Array<Symbol>] names of defined method names
         
     | 
| 
       45 
19 
     | 
    
         
             
                  def self.attr_volatile(*names)
         
     | 
| 
       46 
20 
     | 
    
         
             
                    raise NotImplementedError
         
     | 
| 
       47 
21 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -3,33 +3,41 @@ module Concurrent 
     | 
|
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
                if Concurrent.on_jruby? && Concurrent.java_extensions_loaded?
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
                   
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                    def initialize
         
     | 
| 
       11 
     | 
    
         
            -
                      # nothing to do
         
     | 
| 
      
 6 
     | 
    
         
            +
                  module JRubyAttrVolatile
         
     | 
| 
      
 7 
     | 
    
         
            +
                    def self.included(base)
         
     | 
| 
      
 8 
     | 
    
         
            +
                      base.extend(ClassMethods)
         
     | 
| 
       12 
9 
     | 
    
         
             
                    end
         
     | 
| 
       13 
10 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                     
     | 
| 
       15 
     | 
    
         
            -
                      names 
     | 
| 
      
 11 
     | 
    
         
            +
                    module ClassMethods
         
     | 
| 
      
 12 
     | 
    
         
            +
                      def attr_volatile(*names)
         
     | 
| 
      
 13 
     | 
    
         
            +
                        names.each do |name|
         
     | 
| 
       16 
14 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
      
 15 
     | 
    
         
            +
                          ivar = :"@volatile_#{name}"
         
     | 
| 
       18 
16 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
      
 17 
     | 
    
         
            +
                          class_eval <<-RUBY, __FILE__, __LINE__ + 1
         
     | 
| 
      
 18 
     | 
    
         
            +
                            def #{name}
         
     | 
| 
      
 19 
     | 
    
         
            +
                              instance_variable_get_volatile(:#{ivar})
         
     | 
| 
      
 20 
     | 
    
         
            +
                            end
         
     | 
| 
       23 
21 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
      
 22 
     | 
    
         
            +
                            def #{name}=(value)
         
     | 
| 
      
 23 
     | 
    
         
            +
                              instance_variable_set_volatile(:#{ivar}, value)
         
     | 
| 
      
 24 
     | 
    
         
            +
                            end
         
     | 
| 
      
 25 
     | 
    
         
            +
                          RUBY
         
     | 
| 
       28 
26 
     | 
    
         | 
| 
      
 27 
     | 
    
         
            +
                        end
         
     | 
| 
      
 28 
     | 
    
         
            +
                        names.map { |n| [n, :"#{n}="] }.flatten
         
     | 
| 
       29 
29 
     | 
    
         
             
                      end
         
     | 
| 
       30 
     | 
    
         
            -
                      names.map { |n| [n, :"#{n}="] }.flatten
         
     | 
| 
       31 
30 
     | 
    
         
             
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
      
 33 
     | 
    
         
            +
                  # @!visibility private
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # @!macro internal_implementation_note
         
     | 
| 
      
 35 
     | 
    
         
            +
                  class JRubyObject < AbstractObject
         
     | 
| 
      
 36 
     | 
    
         
            +
                    include JRubyAttrVolatile
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    def initialize
         
     | 
| 
      
 39 
     | 
    
         
            +
                      # nothing to do
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
       33 
41 
     | 
    
         
             
                  end
         
     | 
| 
       34 
42 
     | 
    
         
             
                end
         
     | 
| 
       35 
43 
     | 
    
         
             
              end
         
     |