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,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Concurrent
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Actress
         
     | 
| 
      
 3 
     | 
    
         
            +
                # Allows quick creation of actors with behaviour defined by blocks.
         
     | 
| 
      
 4 
     | 
    
         
            +
                # @example ping
         
     | 
| 
      
 5 
     | 
    
         
            +
                #   AdHoc.spawn :forward, an_actor do |where|
         
     | 
| 
      
 6 
     | 
    
         
            +
                #     # this block has to return proc defining #on_message behaviour
         
     | 
| 
      
 7 
     | 
    
         
            +
                #     -> message { where.tell message  }
         
     | 
| 
      
 8 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 9 
     | 
    
         
            +
                class AdHoc
         
     | 
| 
      
 10 
     | 
    
         
            +
                  include Context
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def initialize(*args, &initializer)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @on_message = Type! initializer.call(*args), Proc
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def on_message(message)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    instance_exec message, &@on_message
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,98 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Concurrent
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Actress
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                # This module is used to define actors. It can be included in any class,
         
     | 
| 
      
 5 
     | 
    
         
            +
                # only requirement is to override {Context#on_message} method.
         
     | 
| 
      
 6 
     | 
    
         
            +
                # @example ping
         
     | 
| 
      
 7 
     | 
    
         
            +
                #  class Ping
         
     | 
| 
      
 8 
     | 
    
         
            +
                #    include Context
         
     | 
| 
      
 9 
     | 
    
         
            +
                #    def on_message(message)
         
     | 
| 
      
 10 
     | 
    
         
            +
                #      message
         
     | 
| 
      
 11 
     | 
    
         
            +
                #    end
         
     | 
| 
      
 12 
     | 
    
         
            +
                #  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                #
         
     | 
| 
      
 14 
     | 
    
         
            +
                #  Ping.spawn(:ping1).ask(:m).value #=> :m
         
     | 
| 
      
 15 
     | 
    
         
            +
                module Context
         
     | 
| 
      
 16 
     | 
    
         
            +
                  include TypeCheck
         
     | 
| 
      
 17 
     | 
    
         
            +
                  include CoreDelegations
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  attr_reader :core
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  # @abstract override to define Actor's behaviour
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # @param [Object] message
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # @return [Object] a result which will be used to set the IVar supplied to Reference#ask
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # @note self should not be returned (or sent to other actors), {#reference} should be used
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #   instead
         
     | 
| 
      
 26 
     | 
    
         
            +
                  def on_message(message)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    raise NotImplementedError
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 31 
     | 
    
         
            +
                  def on_envelope(envelope)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @envelope = envelope
         
     | 
| 
      
 33 
     | 
    
         
            +
                    on_message envelope.message
         
     | 
| 
      
 34 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 35 
     | 
    
         
            +
                    @envelope = nil
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  # @see Actress.spawn
         
     | 
| 
      
 39 
     | 
    
         
            +
                  def spawn(*args, &block)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    Actress.spawn(*args, &block)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  # @see Core#children
         
     | 
| 
      
 44 
     | 
    
         
            +
                  def children
         
     | 
| 
      
 45 
     | 
    
         
            +
                    core.children
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  # @see Core#terminate!
         
     | 
| 
      
 49 
     | 
    
         
            +
                  def terminate!
         
     | 
| 
      
 50 
     | 
    
         
            +
                    core.terminate!
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  # delegates to core.log
         
     | 
| 
      
 54 
     | 
    
         
            +
                  # @see Logging#log
         
     | 
| 
      
 55 
     | 
    
         
            +
                  def log(level, progname, message = nil, &block)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    core.log(level, progname, message, &block)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  private
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  def initialize_core(core)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    @core = Type! core, Core
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  # @return [Envelope] current envelope, accessible inside #on_message processing
         
     | 
| 
      
 66 
     | 
    
         
            +
                  def envelope
         
     | 
| 
      
 67 
     | 
    
         
            +
                    @envelope or raise 'envelope not set'
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  def self.included(base)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    base.extend ClassMethods
         
     | 
| 
      
 72 
     | 
    
         
            +
                    super base
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  module ClassMethods
         
     | 
| 
      
 76 
     | 
    
         
            +
                    # behaves as {Concurrent::Actress.spawn} but class_name is auto-inserted based on receiver
         
     | 
| 
      
 77 
     | 
    
         
            +
                    def spawn(name_or_opts, *args, &block)
         
     | 
| 
      
 78 
     | 
    
         
            +
                      Actress.spawn spawn_optionify(name_or_opts, *args), &block
         
     | 
| 
      
 79 
     | 
    
         
            +
                    end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                    # behaves as {Concurrent::Actress.spawn!} but class_name is auto-inserted based on receiver
         
     | 
| 
      
 82 
     | 
    
         
            +
                    def spawn!(name_or_opts, *args, &block)
         
     | 
| 
      
 83 
     | 
    
         
            +
                      Actress.spawn! spawn_optionify(name_or_opts, *args), &block
         
     | 
| 
      
 84 
     | 
    
         
            +
                    end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                    private
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                    def spawn_optionify(name_or_opts, *args)
         
     | 
| 
      
 89 
     | 
    
         
            +
                      if name_or_opts.is_a? Hash
         
     | 
| 
      
 90 
     | 
    
         
            +
                        name_or_opts.merge class: self
         
     | 
| 
      
 91 
     | 
    
         
            +
                      else
         
     | 
| 
      
 92 
     | 
    
         
            +
                        { class: self, name: name_or_opts, args: args }
         
     | 
| 
      
 93 
     | 
    
         
            +
                      end
         
     | 
| 
      
 94 
     | 
    
         
            +
                    end
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
              end
         
     | 
| 
      
 98 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,228 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Concurrent
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Actress
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                require 'set'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                # Core of the actor
         
     | 
| 
      
 7 
     | 
    
         
            +
                # @note Whole class should be considered private. An user should use {Context}s and {Reference}s only.
         
     | 
| 
      
 8 
     | 
    
         
            +
                # @note devel: core should not block on anything, e.g. it cannot wait on children to terminate
         
     | 
| 
      
 9 
     | 
    
         
            +
                #   that would eat up all threads in task pool and deadlock
         
     | 
| 
      
 10 
     | 
    
         
            +
                class Core
         
     | 
| 
      
 11 
     | 
    
         
            +
                  include TypeCheck
         
     | 
| 
      
 12 
     | 
    
         
            +
                  include Concurrent::Logging
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  # @!attribute [r] reference
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #   @return [Reference] reference to this actor which can be safely passed around
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # @!attribute [r] name
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #   @return [String] the name of this instance, it should be uniq (not enforced right now)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  # @!attribute [r] path
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #   @return [String] a path of this actor. It is used for easier orientation and logging.
         
     | 
| 
      
 20 
     | 
    
         
            +
                  #     Path is constructed recursively with: `parent.path + self.name` up to a {Actress::ROOT},
         
     | 
| 
      
 21 
     | 
    
         
            +
                  #     e.g. `/an_actor/its_child`.
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #     (It will also probably form a supervision path (failures will be reported up to parents)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #     in future versions.)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # @!attribute [r] executor
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #   @return [Executor] which is used to process messages
         
     | 
| 
      
 26 
     | 
    
         
            +
                  # @!attribute [r] terminated
         
     | 
| 
      
 27 
     | 
    
         
            +
                  #   @return [Event] event which will become set when actor is terminated.
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # @!attribute [r] actor_class
         
     | 
| 
      
 29 
     | 
    
         
            +
                  #   @return [Context] a class including {Context} representing Actor's behaviour
         
     | 
| 
      
 30 
     | 
    
         
            +
                  attr_reader :reference, :name, :path, :executor, :terminated, :actor_class
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  # @option opts [String] name
         
     | 
| 
      
 33 
     | 
    
         
            +
                  # @option opts [Reference, nil] parent of an actor spawning this one
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # @option opts [Context] actor_class a class to be instantiated defining Actor's behaviour
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # @option opts [Array<Object>] args arguments for actor_class instantiation
         
     | 
| 
      
 36 
     | 
    
         
            +
                  # @option opts [Executor] executor, default is `Concurrent.configuration.global_task_pool`
         
     | 
| 
      
 37 
     | 
    
         
            +
                  # @option opts [IVar, nil] initialized, if present it'll be set or failed after {Context} initialization
         
     | 
| 
      
 38 
     | 
    
         
            +
                  # @option opts [Proc, nil] logger a proc accepting (level, progname, message = nil, &block) params,
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #   can be used to hook actor instance to any logging system
         
     | 
| 
      
 40 
     | 
    
         
            +
                  # @param [Proc] block for class instantiation
         
     | 
| 
      
 41 
     | 
    
         
            +
                  def initialize(opts = {}, &block)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    @mailbox              = Array.new
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @serialized_execution = SerializedExecution.new
         
     | 
| 
      
 44 
     | 
    
         
            +
                    # noinspection RubyArgCount
         
     | 
| 
      
 45 
     | 
    
         
            +
                    @terminated           = Event.new
         
     | 
| 
      
 46 
     | 
    
         
            +
                    @executor             = Type! opts.fetch(:executor, Concurrent.configuration.global_task_pool), Executor
         
     | 
| 
      
 47 
     | 
    
         
            +
                    @children             = Set.new
         
     | 
| 
      
 48 
     | 
    
         
            +
                    @reference            = Reference.new self
         
     | 
| 
      
 49 
     | 
    
         
            +
                    @name                 = (Type! opts.fetch(:name), String, Symbol).to_s
         
     | 
| 
      
 50 
     | 
    
         
            +
                    @actor                = Concurrent::Atomic.new
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                    parent       = opts[:parent]
         
     | 
| 
      
 53 
     | 
    
         
            +
                    @parent_core = (Type! parent, Reference, NilClass) && parent.send(:core)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    if @parent_core.nil? && @name != '/'
         
     | 
| 
      
 55 
     | 
    
         
            +
                      raise 'only root has no parent'
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    @path   = @parent_core ? File.join(@parent_core.path, @name) : @name
         
     | 
| 
      
 59 
     | 
    
         
            +
                    @logger = opts[:logger]
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    @parent_core.add_child reference if @parent_core
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    @actor_class = actor_class = Child! opts.fetch(:class), Context
         
     | 
| 
      
 64 
     | 
    
         
            +
                    args         = opts.fetch(:args, [])
         
     | 
| 
      
 65 
     | 
    
         
            +
                    initialized  = Type! opts[:initialized], IVar, NilClass
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                    schedule_execution do
         
     | 
| 
      
 68 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 69 
     | 
    
         
            +
                        @actor.value = actor_class.new(*args, &block).
         
     | 
| 
      
 70 
     | 
    
         
            +
                            tap { |a| a.send :initialize_core, self }
         
     | 
| 
      
 71 
     | 
    
         
            +
                        initialized.set true if initialized
         
     | 
| 
      
 72 
     | 
    
         
            +
                      rescue => ex
         
     | 
| 
      
 73 
     | 
    
         
            +
                        log ERROR, ex
         
     | 
| 
      
 74 
     | 
    
         
            +
                        terminate!
         
     | 
| 
      
 75 
     | 
    
         
            +
                        initialized.fail ex if initialized
         
     | 
| 
      
 76 
     | 
    
         
            +
                      end
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  # @return [Reference, nil] of parent actor
         
     | 
| 
      
 81 
     | 
    
         
            +
                  def parent
         
     | 
| 
      
 82 
     | 
    
         
            +
                    @parent_core && @parent_core.reference
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  # @return [Array<Reference>] of children actors
         
     | 
| 
      
 86 
     | 
    
         
            +
                  def children
         
     | 
| 
      
 87 
     | 
    
         
            +
                    guard!
         
     | 
| 
      
 88 
     | 
    
         
            +
                    @children.to_a
         
     | 
| 
      
 89 
     | 
    
         
            +
                  end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 92 
     | 
    
         
            +
                  def add_child(child)
         
     | 
| 
      
 93 
     | 
    
         
            +
                    guard!
         
     | 
| 
      
 94 
     | 
    
         
            +
                    Type! child, Reference
         
     | 
| 
      
 95 
     | 
    
         
            +
                    @children.add child
         
     | 
| 
      
 96 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 100 
     | 
    
         
            +
                  def remove_child(child)
         
     | 
| 
      
 101 
     | 
    
         
            +
                    schedule_execution do
         
     | 
| 
      
 102 
     | 
    
         
            +
                      Type! child, Reference
         
     | 
| 
      
 103 
     | 
    
         
            +
                      @children.delete child
         
     | 
| 
      
 104 
     | 
    
         
            +
                    end
         
     | 
| 
      
 105 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  # is executed by Reference scheduling processing of new messages
         
     | 
| 
      
 109 
     | 
    
         
            +
                  # can be called from other alternative Reference implementations
         
     | 
| 
      
 110 
     | 
    
         
            +
                  # @param [Envelope] envelope
         
     | 
| 
      
 111 
     | 
    
         
            +
                  def on_envelope(envelope)
         
     | 
| 
      
 112 
     | 
    
         
            +
                    schedule_execution do
         
     | 
| 
      
 113 
     | 
    
         
            +
                      if terminated?
         
     | 
| 
      
 114 
     | 
    
         
            +
                        reject_envelope envelope
         
     | 
| 
      
 115 
     | 
    
         
            +
                      else
         
     | 
| 
      
 116 
     | 
    
         
            +
                        @mailbox.push envelope
         
     | 
| 
      
 117 
     | 
    
         
            +
                      end
         
     | 
| 
      
 118 
     | 
    
         
            +
                      process_envelopes?
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
      
 120 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 121 
     | 
    
         
            +
                  end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                  # @note Actor rejects envelopes when terminated.
         
     | 
| 
      
 124 
     | 
    
         
            +
                  # @return [true, false] if actor is terminated
         
     | 
| 
      
 125 
     | 
    
         
            +
                  def terminated?
         
     | 
| 
      
 126 
     | 
    
         
            +
                    @terminated.set?
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                  # Terminates the actor. Any Envelope received after termination is rejected.
         
     | 
| 
      
 130 
     | 
    
         
            +
                  # Terminates all its children, does not wait until they are terminated.
         
     | 
| 
      
 131 
     | 
    
         
            +
                  def terminate!
         
     | 
| 
      
 132 
     | 
    
         
            +
                    guard!
         
     | 
| 
      
 133 
     | 
    
         
            +
                    return nil if terminated?
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                    @children.each do |ch|
         
     | 
| 
      
 136 
     | 
    
         
            +
                      ch.send(:core).tap { |core| core.send(:schedule_execution) { core.terminate! } }
         
     | 
| 
      
 137 
     | 
    
         
            +
                    end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                    @terminated.set
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                    @parent_core.remove_child reference if @parent_core
         
     | 
| 
      
 142 
     | 
    
         
            +
                    @mailbox.each do |envelope|
         
     | 
| 
      
 143 
     | 
    
         
            +
                      reject_envelope envelope
         
     | 
| 
      
 144 
     | 
    
         
            +
                      log DEBUG, "rejected #{envelope.message} from #{envelope.sender_path}"
         
     | 
| 
      
 145 
     | 
    
         
            +
                    end
         
     | 
| 
      
 146 
     | 
    
         
            +
                    @mailbox.clear
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 149 
     | 
    
         
            +
                  end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 152 
     | 
    
         
            +
                  # ensures that we are inside of the executor
         
     | 
| 
      
 153 
     | 
    
         
            +
                  def guard!
         
     | 
| 
      
 154 
     | 
    
         
            +
                    unless Actress.current == reference
         
     | 
| 
      
 155 
     | 
    
         
            +
                      raise "can be called only inside actor #{reference} but was #{Actress.current}"
         
     | 
| 
      
 156 
     | 
    
         
            +
                    end
         
     | 
| 
      
 157 
     | 
    
         
            +
                  end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                  private
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                  # Ensures that only one envelope processing is scheduled with #schedule_execution,
         
     | 
| 
      
 162 
     | 
    
         
            +
                  # this allows other scheduled blocks to be executed before next envelope processing.
         
     | 
| 
      
 163 
     | 
    
         
            +
                  # Simply put this ensures that Core is still responsive to internal calls (like add_child)
         
     | 
| 
      
 164 
     | 
    
         
            +
                  # even though the Actor is flooded with messages.
         
     | 
| 
      
 165 
     | 
    
         
            +
                  def process_envelopes?
         
     | 
| 
      
 166 
     | 
    
         
            +
                    unless @mailbox.empty? || @receive_envelope_scheduled
         
     | 
| 
      
 167 
     | 
    
         
            +
                      @receive_envelope_scheduled = true
         
     | 
| 
      
 168 
     | 
    
         
            +
                      schedule_execution { receive_envelope }
         
     | 
| 
      
 169 
     | 
    
         
            +
                    end
         
     | 
| 
      
 170 
     | 
    
         
            +
                  end
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                  # @return [Context]
         
     | 
| 
      
 173 
     | 
    
         
            +
                  def actor
         
     | 
| 
      
 174 
     | 
    
         
            +
                    @actor.value
         
     | 
| 
      
 175 
     | 
    
         
            +
                  end
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                  # Processes single envelope, calls #process_envelopes? at the end to ensure next envelope
         
     | 
| 
      
 178 
     | 
    
         
            +
                  # scheduling.
         
     | 
| 
      
 179 
     | 
    
         
            +
                  def receive_envelope
         
     | 
| 
      
 180 
     | 
    
         
            +
                    envelope = @mailbox.shift
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                    if terminated?
         
     | 
| 
      
 183 
     | 
    
         
            +
                      reject_envelope envelope
         
     | 
| 
      
 184 
     | 
    
         
            +
                      log FATAL, "this should not be happening #{caller[0]}"
         
     | 
| 
      
 185 
     | 
    
         
            +
                    end
         
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
                    log DEBUG, "received #{envelope.message} from #{envelope.sender_path}"
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                    result = actor.on_envelope envelope
         
     | 
| 
      
 190 
     | 
    
         
            +
                    envelope.ivar.set result unless envelope.ivar.nil?
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 193 
     | 
    
         
            +
                  rescue => error
         
     | 
| 
      
 194 
     | 
    
         
            +
                    log ERROR, error
         
     | 
| 
      
 195 
     | 
    
         
            +
                    terminate!
         
     | 
| 
      
 196 
     | 
    
         
            +
                    envelope.ivar.fail error unless envelope.ivar.nil?
         
     | 
| 
      
 197 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 198 
     | 
    
         
            +
                    @receive_envelope_scheduled = false
         
     | 
| 
      
 199 
     | 
    
         
            +
                    process_envelopes?
         
     | 
| 
      
 200 
     | 
    
         
            +
                  end
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
                  # Schedules blocks to be executed on executor sequentially,
         
     | 
| 
      
 203 
     | 
    
         
            +
                  # sets Actress.current
         
     | 
| 
      
 204 
     | 
    
         
            +
                  def schedule_execution
         
     | 
| 
      
 205 
     | 
    
         
            +
                    @serialized_execution.post(@executor) do
         
     | 
| 
      
 206 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 207 
     | 
    
         
            +
                        Thread.current[:__current_actor__] = reference
         
     | 
| 
      
 208 
     | 
    
         
            +
                        yield
         
     | 
| 
      
 209 
     | 
    
         
            +
                      rescue => e
         
     | 
| 
      
 210 
     | 
    
         
            +
                        log FATAL, e
         
     | 
| 
      
 211 
     | 
    
         
            +
                      ensure
         
     | 
| 
      
 212 
     | 
    
         
            +
                        Thread.current[:__current_actor__] = nil
         
     | 
| 
      
 213 
     | 
    
         
            +
                      end
         
     | 
| 
      
 214 
     | 
    
         
            +
                    end
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 217 
     | 
    
         
            +
                  end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                  def reject_envelope(envelope)
         
     | 
| 
      
 220 
     | 
    
         
            +
                    envelope.reject! ActressTerminated.new(reference)
         
     | 
| 
      
 221 
     | 
    
         
            +
                  end
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                  def log(level, message = nil, &block)
         
     | 
| 
      
 224 
     | 
    
         
            +
                    super level, @path, message, &block
         
     | 
| 
      
 225 
     | 
    
         
            +
                  end
         
     | 
| 
      
 226 
     | 
    
         
            +
                end
         
     | 
| 
      
 227 
     | 
    
         
            +
              end
         
     | 
| 
      
 228 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Concurrent
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Actress
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                # Provides publicly expose-able methods from {Core}.
         
     | 
| 
      
 5 
     | 
    
         
            +
                module CoreDelegations
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 7 
     | 
    
         
            +
                    core.name
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def path
         
     | 
| 
      
 11 
     | 
    
         
            +
                    core.path
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def parent
         
     | 
| 
      
 15 
     | 
    
         
            +
                    core.parent
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def terminated?
         
     | 
| 
      
 19 
     | 
    
         
            +
                    core.terminated?
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def terminated
         
     | 
| 
      
 23 
     | 
    
         
            +
                    core.terminated
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def reference
         
     | 
| 
      
 27 
     | 
    
         
            +
                    core.reference
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def executor
         
     | 
| 
      
 31 
     | 
    
         
            +
                    core.executor
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def actor_class
         
     | 
| 
      
 35 
     | 
    
         
            +
                    core.actor_class
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  alias_method :ref, :reference
         
     | 
| 
      
 39 
     | 
    
         
            +
                  alias_method :actress_class, :actor_class
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Concurrent
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Actress
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Envelope
         
     | 
| 
      
 4 
     | 
    
         
            +
                  include TypeCheck
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  # @!attribute [r] message
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #   @return [Object] a message
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # @!attribute [r] ivar
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #   @return [IVar] an ivar which becomes resolved after message is processed
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # @!attribute [r] sender
         
     | 
| 
      
 11 
     | 
    
         
            +
                  #   @return [Reference, Thread] an actor or thread sending the message
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # @!attribute [r] address
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #   @return [Reference] where this message will be delivered
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  attr_reader :message, :ivar, :sender, :address
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def initialize(message, ivar, sender, address)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @message = message
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @ivar    = Type! ivar, IVar, NilClass
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @sender  = Type! sender, Reference, Thread
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @address = Type! address, Reference
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def sender_path
         
     | 
| 
      
 25 
     | 
    
         
            +
                    if sender.is_a? Reference
         
     | 
| 
      
 26 
     | 
    
         
            +
                      sender.path
         
     | 
| 
      
 27 
     | 
    
         
            +
                    else
         
     | 
| 
      
 28 
     | 
    
         
            +
                      sender.to_s
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  def address_path
         
     | 
| 
      
 33 
     | 
    
         
            +
                    address.path
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def reject!(error)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    ivar.fail error unless ivar.nil?
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     |