concurrent-ruby 0.7.0.rc0-x86-solaris-2.11
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 +7 -0
 - data/LICENSE.txt +21 -0
 - data/README.md +166 -0
 - data/ext/concurrent_ruby_ext/atomic_reference.c +78 -0
 - data/ext/concurrent_ruby_ext/atomic_reference.h +12 -0
 - data/ext/concurrent_ruby_ext/extconf.rb +59 -0
 - data/ext/concurrent_ruby_ext/rb_concurrent.c +28 -0
 - data/lib/concurrent.rb +45 -0
 - data/lib/concurrent/actress.rb +221 -0
 - data/lib/concurrent/actress/ad_hoc.rb +20 -0
 - data/lib/concurrent/actress/context.rb +98 -0
 - data/lib/concurrent/actress/core.rb +228 -0
 - data/lib/concurrent/actress/core_delegations.rb +42 -0
 - data/lib/concurrent/actress/envelope.rb +41 -0
 - data/lib/concurrent/actress/errors.rb +14 -0
 - data/lib/concurrent/actress/reference.rb +64 -0
 - data/lib/concurrent/actress/type_check.rb +48 -0
 - data/lib/concurrent/agent.rb +232 -0
 - data/lib/concurrent/async.rb +319 -0
 - data/lib/concurrent/atomic.rb +46 -0
 - data/lib/concurrent/atomic/atomic_boolean.rb +157 -0
 - data/lib/concurrent/atomic/atomic_fixnum.rb +162 -0
 - data/lib/concurrent/atomic/condition.rb +67 -0
 - data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +118 -0
 - data/lib/concurrent/atomic/copy_on_write_observer_set.rb +117 -0
 - data/lib/concurrent/atomic/count_down_latch.rb +116 -0
 - data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
 - data/lib/concurrent/atomic/event.rb +98 -0
 - data/lib/concurrent/atomic/thread_local_var.rb +117 -0
 - data/lib/concurrent/atomic_reference/concurrent_update_error.rb +7 -0
 - data/lib/concurrent/atomic_reference/delegated_update.rb +28 -0
 - data/lib/concurrent/atomic_reference/direct_update.rb +28 -0
 - data/lib/concurrent/atomic_reference/jruby.rb +8 -0
 - data/lib/concurrent/atomic_reference/mutex_atomic.rb +47 -0
 - data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +24 -0
 - data/lib/concurrent/atomic_reference/rbx.rb +16 -0
 - data/lib/concurrent/atomic_reference/ruby.rb +16 -0
 - data/lib/concurrent/atomics.rb +10 -0
 - data/lib/concurrent/channel/buffered_channel.rb +85 -0
 - data/lib/concurrent/channel/channel.rb +41 -0
 - data/lib/concurrent/channel/unbuffered_channel.rb +34 -0
 - data/lib/concurrent/channel/waitable_list.rb +40 -0
 - data/lib/concurrent/channels.rb +5 -0
 - data/lib/concurrent/collection/blocking_ring_buffer.rb +71 -0
 - data/lib/concurrent/collection/priority_queue.rb +305 -0
 - data/lib/concurrent/collection/ring_buffer.rb +59 -0
 - data/lib/concurrent/collections.rb +3 -0
 - data/lib/concurrent/configuration.rb +158 -0
 - data/lib/concurrent/dataflow.rb +91 -0
 - data/lib/concurrent/delay.rb +112 -0
 - data/lib/concurrent/dereferenceable.rb +101 -0
 - data/lib/concurrent/errors.rb +30 -0
 - data/lib/concurrent/exchanger.rb +34 -0
 - data/lib/concurrent/executor/cached_thread_pool.rb +44 -0
 - data/lib/concurrent/executor/executor.rb +229 -0
 - data/lib/concurrent/executor/fixed_thread_pool.rb +33 -0
 - data/lib/concurrent/executor/immediate_executor.rb +16 -0
 - data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
 - data/lib/concurrent/executor/java_fixed_thread_pool.rb +33 -0
 - data/lib/concurrent/executor/java_single_thread_executor.rb +21 -0
 - data/lib/concurrent/executor/java_thread_pool_executor.rb +187 -0
 - data/lib/concurrent/executor/per_thread_executor.rb +24 -0
 - data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
 - data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +32 -0
 - data/lib/concurrent/executor/ruby_single_thread_executor.rb +73 -0
 - data/lib/concurrent/executor/ruby_thread_pool_executor.rb +286 -0
 - data/lib/concurrent/executor/ruby_thread_pool_worker.rb +72 -0
 - data/lib/concurrent/executor/safe_task_executor.rb +35 -0
 - data/lib/concurrent/executor/serialized_execution.rb +90 -0
 - data/lib/concurrent/executor/single_thread_executor.rb +35 -0
 - data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
 - data/lib/concurrent/executor/timer_set.rb +143 -0
 - data/lib/concurrent/executors.rb +9 -0
 - data/lib/concurrent/future.rb +124 -0
 - data/lib/concurrent/ivar.rb +111 -0
 - data/lib/concurrent/logging.rb +17 -0
 - data/lib/concurrent/mvar.rb +200 -0
 - data/lib/concurrent/obligation.rb +171 -0
 - data/lib/concurrent/observable.rb +40 -0
 - data/lib/concurrent/options_parser.rb +46 -0
 - data/lib/concurrent/promise.rb +169 -0
 - data/lib/concurrent/scheduled_task.rb +78 -0
 - data/lib/concurrent/supervisor.rb +343 -0
 - data/lib/concurrent/timer_task.rb +341 -0
 - data/lib/concurrent/tvar.rb +252 -0
 - data/lib/concurrent/utilities.rb +3 -0
 - data/lib/concurrent/utility/processor_count.rb +150 -0
 - data/lib/concurrent/utility/timeout.rb +35 -0
 - data/lib/concurrent/utility/timer.rb +21 -0
 - data/lib/concurrent/version.rb +3 -0
 - data/lib/concurrent_ruby.rb +1 -0
 - data/lib/concurrent_ruby_ext.so +0 -0
 - data/lib/extension_helper.rb +9 -0
 - metadata +140 -0
 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'concurrent/atomic_reference/concurrent_update_error'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'concurrent/atomic_reference/mutex_atomic'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            begin
         
     | 
| 
      
 5 
     | 
    
         
            +
              # force fallback impl with FORCE_ATOMIC_FALLBACK=1
         
     | 
| 
      
 6 
     | 
    
         
            +
              if /[^0fF]/ =~ ENV['FORCE_ATOMIC_FALLBACK']
         
     | 
| 
      
 7 
     | 
    
         
            +
                ruby_engine = 'mutex_atomic'
         
     | 
| 
      
 8 
     | 
    
         
            +
              else
         
     | 
| 
      
 9 
     | 
    
         
            +
                ruby_engine = defined?(RUBY_ENGINE)? RUBY_ENGINE : 'ruby'
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              require "concurrent/atomic_reference/#{ruby_engine}"
         
     | 
| 
      
 13 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 14 
     | 
    
         
            +
              warn 'Compiled extensions not installed, pure Ruby Atomic will be used.'
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            if defined? Concurrent::JavaAtomic
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              class Concurrent::Atomic < Concurrent::JavaAtomic
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            elsif defined? Concurrent::CAtomic
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              class Concurrent::Atomic < Concurrent::CAtomic
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            elsif defined? Concurrent::RbxAtomic
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              class Concurrent::Atomic < Concurrent::RbxAtomic
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            else
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              class Concurrent::Atomic < Concurrent::MutexAtomic
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            class Atomic < Concurrent::Atomic
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              ConcurrentUpdateError = Class.new(Concurrent::ConcurrentUpdateError)
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              def initialize(*args)
         
     | 
| 
      
 43 
     | 
    
         
            +
                warn "[DEPRECATED] Please use Concurrent::Atomic instead."
         
     | 
| 
      
 44 
     | 
    
         
            +
                super
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,157 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Concurrent
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              # @!macro [attach] atomic_boolean
         
     | 
| 
      
 4 
     | 
    
         
            +
              #
         
     | 
| 
      
 5 
     | 
    
         
            +
              #   A boolean value that can be updated atomically. Reads and writes to an atomic
         
     | 
| 
      
 6 
     | 
    
         
            +
              #   boolean and thread-safe and guaranteed to succeed. Reads and writes may block
         
     | 
| 
      
 7 
     | 
    
         
            +
              #   briefly but no explicit locking is required.
         
     | 
| 
      
 8 
     | 
    
         
            +
              #
         
     | 
| 
      
 9 
     | 
    
         
            +
              #   @since 0.6.0
         
     | 
| 
      
 10 
     | 
    
         
            +
              #   @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean
         
     | 
| 
      
 11 
     | 
    
         
            +
              class MutexAtomicBoolean
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # @!macro [attach] atomic_boolean_method_initialize
         
     | 
| 
      
 14 
     | 
    
         
            +
                #
         
     | 
| 
      
 15 
     | 
    
         
            +
                # Creates a new `AtomicBoolean` with the given initial value.
         
     | 
| 
      
 16 
     | 
    
         
            +
                #
         
     | 
| 
      
 17 
     | 
    
         
            +
                # @param [Boolean] initial the initial value
         
     | 
| 
      
 18 
     | 
    
         
            +
                def initialize(initial = false)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @value = !!initial
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @mutex = Mutex.new
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                # @!macro [attach] atomic_boolean_method_value
         
     | 
| 
      
 24 
     | 
    
         
            +
                #
         
     | 
| 
      
 25 
     | 
    
         
            +
                #   Retrieves the current `Boolean` value.
         
     | 
| 
      
 26 
     | 
    
         
            +
                #
         
     | 
| 
      
 27 
     | 
    
         
            +
                #   @return [Boolean] the current value
         
     | 
| 
      
 28 
     | 
    
         
            +
                def value
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @value
         
     | 
| 
      
 31 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                # @!macro [attach] atomic_boolean_method_value_eq
         
     | 
| 
      
 36 
     | 
    
         
            +
                #
         
     | 
| 
      
 37 
     | 
    
         
            +
                #   Explicitly sets the value.
         
     | 
| 
      
 38 
     | 
    
         
            +
                #
         
     | 
| 
      
 39 
     | 
    
         
            +
                #   @param [Boolean] value the new value to be set
         
     | 
| 
      
 40 
     | 
    
         
            +
                #
         
     | 
| 
      
 41 
     | 
    
         
            +
                #   @return [Boolean] the current value
         
     | 
| 
      
 42 
     | 
    
         
            +
                def value=(value)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @value = !!value
         
     | 
| 
      
 45 
     | 
    
         
            +
                  @value
         
     | 
| 
      
 46 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                # @!macro [attach] atomic_boolean_method_is_true
         
     | 
| 
      
 51 
     | 
    
         
            +
                #
         
     | 
| 
      
 52 
     | 
    
         
            +
                #   Is the current value `true`?
         
     | 
| 
      
 53 
     | 
    
         
            +
                #
         
     | 
| 
      
 54 
     | 
    
         
            +
                #   @return [Boolean] true if the current value is `true`, else false
         
     | 
| 
      
 55 
     | 
    
         
            +
                def true?
         
     | 
| 
      
 56 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 57 
     | 
    
         
            +
                  @value
         
     | 
| 
      
 58 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                # @!macro [attach] atomic_boolean_method_is_false
         
     | 
| 
      
 63 
     | 
    
         
            +
                #
         
     | 
| 
      
 64 
     | 
    
         
            +
                #   Is the current value `true`?false
         
     | 
| 
      
 65 
     | 
    
         
            +
                #
         
     | 
| 
      
 66 
     | 
    
         
            +
                #   @return [Boolean] true if the current value is `false`, else false
         
     | 
| 
      
 67 
     | 
    
         
            +
                def false?
         
     | 
| 
      
 68 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 69 
     | 
    
         
            +
                  !@value
         
     | 
| 
      
 70 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 71 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                # @!macro [attach] atomic_boolean_method_make_true
         
     | 
| 
      
 75 
     | 
    
         
            +
                #
         
     | 
| 
      
 76 
     | 
    
         
            +
                #   Explicitly sets the value to true.
         
     | 
| 
      
 77 
     | 
    
         
            +
                #
         
     | 
| 
      
 78 
     | 
    
         
            +
                #   @return [Boolean] true is value has changed, otherwise false
         
     | 
| 
      
 79 
     | 
    
         
            +
                def make_true
         
     | 
| 
      
 80 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 81 
     | 
    
         
            +
                  old = @value
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @value = true
         
     | 
| 
      
 83 
     | 
    
         
            +
                  !old
         
     | 
| 
      
 84 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 85 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                # @!macro [attach] atomic_boolean_method_make_false
         
     | 
| 
      
 89 
     | 
    
         
            +
                #
         
     | 
| 
      
 90 
     | 
    
         
            +
                #   Explicitly sets the value to false.
         
     | 
| 
      
 91 
     | 
    
         
            +
                #
         
     | 
| 
      
 92 
     | 
    
         
            +
                #   @return [Boolean] true is value has changed, otherwise false
         
     | 
| 
      
 93 
     | 
    
         
            +
                def make_false
         
     | 
| 
      
 94 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 95 
     | 
    
         
            +
                  old = @value
         
     | 
| 
      
 96 
     | 
    
         
            +
                  @value = false
         
     | 
| 
      
 97 
     | 
    
         
            +
                  old
         
     | 
| 
      
 98 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 99 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
              end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              if RUBY_PLATFORM == 'java'
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                # @!macro atomic_boolean
         
     | 
| 
      
 106 
     | 
    
         
            +
                class JavaAtomicBoolean
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  # @!macro atomic_boolean_method_initialize
         
     | 
| 
      
 109 
     | 
    
         
            +
                  #
         
     | 
| 
      
 110 
     | 
    
         
            +
                  def initialize(initial = false)
         
     | 
| 
      
 111 
     | 
    
         
            +
                    @atomic = java.util.concurrent.atomic.AtomicBoolean.new(!!initial)
         
     | 
| 
      
 112 
     | 
    
         
            +
                  end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                  # @!macro atomic_boolean_method_value
         
     | 
| 
      
 115 
     | 
    
         
            +
                  #
         
     | 
| 
      
 116 
     | 
    
         
            +
                  def value
         
     | 
| 
      
 117 
     | 
    
         
            +
                    @atomic.get
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                  # @!macro atomic_boolean_method_value_eq
         
     | 
| 
      
 121 
     | 
    
         
            +
                  #
         
     | 
| 
      
 122 
     | 
    
         
            +
                  def value=(value)
         
     | 
| 
      
 123 
     | 
    
         
            +
                    @atomic.set(!!value)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                  # @!macro [attach] atomic_boolean_method_is_true
         
     | 
| 
      
 127 
     | 
    
         
            +
                  def true?
         
     | 
| 
      
 128 
     | 
    
         
            +
                    @atomic.get
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  # @!macro [attach] atomic_boolean_method_is_false
         
     | 
| 
      
 132 
     | 
    
         
            +
                  def false?
         
     | 
| 
      
 133 
     | 
    
         
            +
                    !@atomic.get
         
     | 
| 
      
 134 
     | 
    
         
            +
                  end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                  # @!macro atomic_boolean_method_make_true
         
     | 
| 
      
 137 
     | 
    
         
            +
                  def make_true
         
     | 
| 
      
 138 
     | 
    
         
            +
                    @atomic.compareAndSet(false, true)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  # @!macro atomic_boolean_method_make_false
         
     | 
| 
      
 142 
     | 
    
         
            +
                  def make_false
         
     | 
| 
      
 143 
     | 
    
         
            +
                    @atomic.compareAndSet(true, false)
         
     | 
| 
      
 144 
     | 
    
         
            +
                  end
         
     | 
| 
      
 145 
     | 
    
         
            +
                end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                # @!macro atomic_boolean
         
     | 
| 
      
 148 
     | 
    
         
            +
                class AtomicBoolean < JavaAtomicBoolean
         
     | 
| 
      
 149 
     | 
    
         
            +
                end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
              else
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                # @!macro atomic_boolean
         
     | 
| 
      
 154 
     | 
    
         
            +
                class AtomicBoolean < MutexAtomicBoolean
         
     | 
| 
      
 155 
     | 
    
         
            +
                end
         
     | 
| 
      
 156 
     | 
    
         
            +
              end
         
     | 
| 
      
 157 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,162 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Concurrent
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              # @!macro [attach] atomic_fixnum
         
     | 
| 
      
 4 
     | 
    
         
            +
              #
         
     | 
| 
      
 5 
     | 
    
         
            +
              #   A numeric value that can be updated atomically. Reads and writes to an atomic
         
     | 
| 
      
 6 
     | 
    
         
            +
              #   fixnum and thread-safe and guaranteed to succeed. Reads and writes may block
         
     | 
| 
      
 7 
     | 
    
         
            +
              #   briefly but no explicit locking is required.
         
     | 
| 
      
 8 
     | 
    
         
            +
              #
         
     | 
| 
      
 9 
     | 
    
         
            +
              #   @since 0.5.0
         
     | 
| 
      
 10 
     | 
    
         
            +
              #   @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong
         
     | 
| 
      
 11 
     | 
    
         
            +
              class MutexAtomicFixnum
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # @!macro [attach] atomic_fixnum_method_initialize
         
     | 
| 
      
 14 
     | 
    
         
            +
                #
         
     | 
| 
      
 15 
     | 
    
         
            +
                # Creates a new `AtomicFixnum` with the given initial value.
         
     | 
| 
      
 16 
     | 
    
         
            +
                #
         
     | 
| 
      
 17 
     | 
    
         
            +
                # @param [Fixnum] init the initial value
         
     | 
| 
      
 18 
     | 
    
         
            +
                # @raise [ArgumentError] if the initial value is not a `Fixnum`
         
     | 
| 
      
 19 
     | 
    
         
            +
                def initialize(init = 0)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @value = init
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @mutex = Mutex.new
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                # @!macro [attach] atomic_fixnum_method_value
         
     | 
| 
      
 26 
     | 
    
         
            +
                #
         
     | 
| 
      
 27 
     | 
    
         
            +
                #   Retrieves the current `Fixnum` value.
         
     | 
| 
      
 28 
     | 
    
         
            +
                #
         
     | 
| 
      
 29 
     | 
    
         
            +
                #   @return [Fixnum] the current value
         
     | 
| 
      
 30 
     | 
    
         
            +
                def value
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @value
         
     | 
| 
      
 33 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                # @!macro [attach] atomic_fixnum_method_value_eq
         
     | 
| 
      
 38 
     | 
    
         
            +
                #
         
     | 
| 
      
 39 
     | 
    
         
            +
                #   Explicitly sets the value.
         
     | 
| 
      
 40 
     | 
    
         
            +
                #
         
     | 
| 
      
 41 
     | 
    
         
            +
                #   @param [Fixnum] value the new value to be set
         
     | 
| 
      
 42 
     | 
    
         
            +
                #
         
     | 
| 
      
 43 
     | 
    
         
            +
                #   @return [Fixnum] the current value
         
     | 
| 
      
 44 
     | 
    
         
            +
                #
         
     | 
| 
      
 45 
     | 
    
         
            +
                #   @raise [ArgumentError] if the new value is not a `Fixnum`
         
     | 
| 
      
 46 
     | 
    
         
            +
                def value=(value)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @value = value
         
     | 
| 
      
 50 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                # @!macro [attach] atomic_fixnum_method_increment
         
     | 
| 
      
 55 
     | 
    
         
            +
                #
         
     | 
| 
      
 56 
     | 
    
         
            +
                #   Increases the current value by 1.
         
     | 
| 
      
 57 
     | 
    
         
            +
                #
         
     | 
| 
      
 58 
     | 
    
         
            +
                #   @return [Fixnum] the current value after incrementation
         
     | 
| 
      
 59 
     | 
    
         
            +
                def increment
         
     | 
| 
      
 60 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @value += 1
         
     | 
| 
      
 62 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 63 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                alias_method :up, :increment
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                # @!macro [attach] atomic_fixnum_method_decrement
         
     | 
| 
      
 69 
     | 
    
         
            +
                #
         
     | 
| 
      
 70 
     | 
    
         
            +
                #   Decreases the current value by 1.
         
     | 
| 
      
 71 
     | 
    
         
            +
                #
         
     | 
| 
      
 72 
     | 
    
         
            +
                #   @return [Fixnum] the current value after decrementation
         
     | 
| 
      
 73 
     | 
    
         
            +
                def decrement
         
     | 
| 
      
 74 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 75 
     | 
    
         
            +
                  @value -= 1
         
     | 
| 
      
 76 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 77 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                alias_method :down, :decrement
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                # @!macro [attach] atomic_fixnum_method_compare_and_set
         
     | 
| 
      
 83 
     | 
    
         
            +
                # 
         
     | 
| 
      
 84 
     | 
    
         
            +
                #   Atomically sets the value to the given updated value if the current
         
     | 
| 
      
 85 
     | 
    
         
            +
                #   value == the expected value.
         
     | 
| 
      
 86 
     | 
    
         
            +
                #
         
     | 
| 
      
 87 
     | 
    
         
            +
                #   @param [Fixnum] expect the expected value
         
     | 
| 
      
 88 
     | 
    
         
            +
                #   @param [Fixnum] update the new value
         
     | 
| 
      
 89 
     | 
    
         
            +
                #
         
     | 
| 
      
 90 
     | 
    
         
            +
                #   @return [Boolean] true if the value was updated else false 
         
     | 
| 
      
 91 
     | 
    
         
            +
                def compare_and_set(expect, update)
         
     | 
| 
      
 92 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 93 
     | 
    
         
            +
                  if @value == expect
         
     | 
| 
      
 94 
     | 
    
         
            +
                    @value = update
         
     | 
| 
      
 95 
     | 
    
         
            +
                    true
         
     | 
| 
      
 96 
     | 
    
         
            +
                  else
         
     | 
| 
      
 97 
     | 
    
         
            +
                    false
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 100 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
              end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
              if RUBY_PLATFORM == 'java'
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                # @!macro atomic_fixnum
         
     | 
| 
      
 107 
     | 
    
         
            +
                class JavaAtomicFixnum
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  # @!macro atomic_fixnum_method_initialize
         
     | 
| 
      
 110 
     | 
    
         
            +
                  #
         
     | 
| 
      
 111 
     | 
    
         
            +
                  def initialize(init = 0)
         
     | 
| 
      
 112 
     | 
    
         
            +
                    raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
         
     | 
| 
      
 113 
     | 
    
         
            +
                    @atomic = java.util.concurrent.atomic.AtomicLong.new(init)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                  # @!macro atomic_fixnum_method_value
         
     | 
| 
      
 117 
     | 
    
         
            +
                  #
         
     | 
| 
      
 118 
     | 
    
         
            +
                  def value
         
     | 
| 
      
 119 
     | 
    
         
            +
                    @atomic.get
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                  # @!macro atomic_fixnum_method_value_eq
         
     | 
| 
      
 123 
     | 
    
         
            +
                  #
         
     | 
| 
      
 124 
     | 
    
         
            +
                  def value=(value)
         
     | 
| 
      
 125 
     | 
    
         
            +
                    raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
         
     | 
| 
      
 126 
     | 
    
         
            +
                    @atomic.set(value)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                  # @!macro atomic_fixnum_method_increment
         
     | 
| 
      
 130 
     | 
    
         
            +
                  #
         
     | 
| 
      
 131 
     | 
    
         
            +
                  def increment
         
     | 
| 
      
 132 
     | 
    
         
            +
                    @atomic.increment_and_get
         
     | 
| 
      
 133 
     | 
    
         
            +
                  end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                  alias_method :up, :increment
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                  # @!macro atomic_fixnum_method_decrement
         
     | 
| 
      
 138 
     | 
    
         
            +
                  #
         
     | 
| 
      
 139 
     | 
    
         
            +
                  def decrement
         
     | 
| 
      
 140 
     | 
    
         
            +
                    @atomic.decrement_and_get
         
     | 
| 
      
 141 
     | 
    
         
            +
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                  alias_method :down, :decrement
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                  # @!macro atomic_fixnum_method_compare_and_set
         
     | 
| 
      
 146 
     | 
    
         
            +
                  #
         
     | 
| 
      
 147 
     | 
    
         
            +
                  def compare_and_set(expect, update)
         
     | 
| 
      
 148 
     | 
    
         
            +
                    @atomic.compare_and_set(expect, update)
         
     | 
| 
      
 149 
     | 
    
         
            +
                  end
         
     | 
| 
      
 150 
     | 
    
         
            +
                end
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                # @!macro atomic_fixnum
         
     | 
| 
      
 153 
     | 
    
         
            +
                class AtomicFixnum < JavaAtomicFixnum
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
              else
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                # @!macro atomic_fixnum
         
     | 
| 
      
 159 
     | 
    
         
            +
                class AtomicFixnum < MutexAtomicFixnum
         
     | 
| 
      
 160 
     | 
    
         
            +
                end
         
     | 
| 
      
 161 
     | 
    
         
            +
              end
         
     | 
| 
      
 162 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,67 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Concurrent
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              # Condition is a better implementation of standard Ruby ConditionVariable.
         
     | 
| 
      
 4 
     | 
    
         
            +
              # The biggest difference is the wait return value: Condition#wait returns
         
     | 
| 
      
 5 
     | 
    
         
            +
              # Condition::Result which make possible to know if waiting thread has been woken up
         
     | 
| 
      
 6 
     | 
    
         
            +
              # by an another thread (using #signal or #broadcast) or due to timeout.
         
     | 
| 
      
 7 
     | 
    
         
            +
              #
         
     | 
| 
      
 8 
     | 
    
         
            +
              # Every #wait must be guarded by a locked Mutex or a ThreadError will be risen.
         
     | 
| 
      
 9 
     | 
    
         
            +
              # Although it's not mandatory, it's recommended to call also #signal and #broadcast within
         
     | 
| 
      
 10 
     | 
    
         
            +
              # the same mutex
         
     | 
| 
      
 11 
     | 
    
         
            +
              class Condition
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                class Result
         
     | 
| 
      
 14 
     | 
    
         
            +
                  def initialize(remaining_time)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @remaining_time = remaining_time
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  attr_reader :remaining_time
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  # @return [Boolean] true if current thread has been waken up by a #signal or a #broadcast call, otherwise false
         
     | 
| 
      
 21 
     | 
    
         
            +
                  def woken_up?
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @remaining_time.nil? || @remaining_time > 0
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  # @return [Boolean] true if current thread has been waken up due to a timeout, otherwise false
         
     | 
| 
      
 26 
     | 
    
         
            +
                  def timed_out?
         
     | 
| 
      
 27 
     | 
    
         
            +
                    @remaining_time != nil && @remaining_time <= 0
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  alias_method :can_wait?, :woken_up?
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @condition = ConditionVariable.new
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                # @param [Mutex] mutex the locked mutex guarding the wait
         
     | 
| 
      
 39 
     | 
    
         
            +
                # @param [Object] timeout nil means no timeout
         
     | 
| 
      
 40 
     | 
    
         
            +
                # @return [Result]
         
     | 
| 
      
 41 
     | 
    
         
            +
                def wait(mutex, timeout = nil)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  start_time = Time.now.to_f
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @condition.wait(mutex, timeout)
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  if timeout.nil?
         
     | 
| 
      
 46 
     | 
    
         
            +
                    Result.new(nil)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  else
         
     | 
| 
      
 48 
     | 
    
         
            +
                    Result.new(start_time + timeout - Time.now.to_f)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                # Wakes up a waiting thread
         
     | 
| 
      
 53 
     | 
    
         
            +
                # @return [true]
         
     | 
| 
      
 54 
     | 
    
         
            +
                def signal
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @condition.signal
         
     | 
| 
      
 56 
     | 
    
         
            +
                  true
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                # Wakes up all waiting threads
         
     | 
| 
      
 60 
     | 
    
         
            +
                # @return [true]
         
     | 
| 
      
 61 
     | 
    
         
            +
                def broadcast
         
     | 
| 
      
 62 
     | 
    
         
            +
                  @condition.broadcast
         
     | 
| 
      
 63 
     | 
    
         
            +
                  true
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,118 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Concurrent
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              # A thread safe observer set implemented using copy-on-read approach:
         
     | 
| 
      
 4 
     | 
    
         
            +
              # observers are added and removed from a thread safe collection; every time
         
     | 
| 
      
 5 
     | 
    
         
            +
              # a notification is required the internal data structure is copied to
         
     | 
| 
      
 6 
     | 
    
         
            +
              # prevent concurrency issues
         
     | 
| 
      
 7 
     | 
    
         
            +
              class CopyOnNotifyObserverSet
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @mutex = Mutex.new
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @observers = {}
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                # Adds an observer to this set
         
     | 
| 
      
 15 
     | 
    
         
            +
                # If a block is passed, the observer will be created by this method and no other params should be passed
         
     | 
| 
      
 16 
     | 
    
         
            +
                # @param [Object] observer the observer to add
         
     | 
| 
      
 17 
     | 
    
         
            +
                # @param [Symbol] func the function to call on the observer during notification. Default is :update
         
     | 
| 
      
 18 
     | 
    
         
            +
                # @return [Object] the added observer
         
     | 
| 
      
 19 
     | 
    
         
            +
                def add_observer(observer=nil, func=:update, &block)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  if observer.nil? && block.nil?
         
     | 
| 
      
 21 
     | 
    
         
            +
                    raise ArgumentError, 'should pass observer as a first argument or block'
         
     | 
| 
      
 22 
     | 
    
         
            +
                  elsif observer && block
         
     | 
| 
      
 23 
     | 
    
         
            +
                    raise ArgumentError.new('cannot provide both an observer and a block')
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  if block
         
     | 
| 
      
 27 
     | 
    
         
            +
                    observer = block
         
     | 
| 
      
 28 
     | 
    
         
            +
                    func = :call
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @mutex.lock
         
     | 
| 
      
 33 
     | 
    
         
            +
                    @observers[observer] = func
         
     | 
| 
      
 34 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 35 
     | 
    
         
            +
                    @mutex.unlock
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    observer
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                # @param [Object] observer the observer to remove
         
     | 
| 
      
 42 
     | 
    
         
            +
                # @return [Object] the deleted observer
         
     | 
| 
      
 43 
     | 
    
         
            +
                def delete_observer(observer)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 45 
     | 
    
         
            +
                  @observers.delete(observer)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  observer
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                # Deletes all observers
         
     | 
| 
      
 52 
     | 
    
         
            +
                # @return [CopyOnWriteObserverSet] self
         
     | 
| 
      
 53 
     | 
    
         
            +
                def delete_observers
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @observers.clear
         
     | 
| 
      
 56 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  self
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                # @return [Integer] the observers count
         
     | 
| 
      
 62 
     | 
    
         
            +
                def count_observers
         
     | 
| 
      
 63 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 64 
     | 
    
         
            +
                  result = @observers.count
         
     | 
| 
      
 65 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  result
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                # Notifies all registered observers with optional args
         
     | 
| 
      
 71 
     | 
    
         
            +
                # @param [Object] args arguments to be passed to each observer
         
     | 
| 
      
 72 
     | 
    
         
            +
                # @return [CopyOnWriteObserverSet] self
         
     | 
| 
      
 73 
     | 
    
         
            +
                def notify_observers(*args, &block)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  observers = duplicate_observers
         
     | 
| 
      
 75 
     | 
    
         
            +
                  notify_to(observers, *args, &block)
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  self
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                # Notifies all registered observers with optional args and deletes them.
         
     | 
| 
      
 81 
     | 
    
         
            +
                #
         
     | 
| 
      
 82 
     | 
    
         
            +
                # @param [Object] args arguments to be passed to each observer
         
     | 
| 
      
 83 
     | 
    
         
            +
                # @return [CopyOnWriteObserverSet] self
         
     | 
| 
      
 84 
     | 
    
         
            +
                def notify_and_delete_observers(*args, &block)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  observers = duplicate_and_clear_observers
         
     | 
| 
      
 86 
     | 
    
         
            +
                  notify_to(observers, *args, &block)
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  self
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                private
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                def duplicate_and_clear_observers
         
     | 
| 
      
 94 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 95 
     | 
    
         
            +
                  observers = @observers.dup
         
     | 
| 
      
 96 
     | 
    
         
            +
                  @observers.clear
         
     | 
| 
      
 97 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  observers
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                def duplicate_observers
         
     | 
| 
      
 103 
     | 
    
         
            +
                  @mutex.lock
         
     | 
| 
      
 104 
     | 
    
         
            +
                  observers = @observers.dup
         
     | 
| 
      
 105 
     | 
    
         
            +
                  @mutex.unlock
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                  observers
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                def notify_to(observers, *args)
         
     | 
| 
      
 111 
     | 
    
         
            +
                  raise ArgumentError.new('cannot give arguments and a block') if block_given? && !args.empty?
         
     | 
| 
      
 112 
     | 
    
         
            +
                  observers.each do |observer, function|
         
     | 
| 
      
 113 
     | 
    
         
            +
                    args = yield if block_given?
         
     | 
| 
      
 114 
     | 
    
         
            +
                    observer.send(function, *args)
         
     | 
| 
      
 115 
     | 
    
         
            +
                  end
         
     | 
| 
      
 116 
     | 
    
         
            +
                end
         
     | 
| 
      
 117 
     | 
    
         
            +
              end
         
     | 
| 
      
 118 
     | 
    
         
            +
            end
         
     |