<commit_before>module Celluloid
  # A proxy object returned from Celluloid::Actor.spawn/spawn_link which
  # dispatches calls and casts to normal Ruby objects which are running inside
  # of their own threads.
  class ActorProxy
    # FIXME: not nearly enough methods are delegated here
    attr_reader :mailbox

    def initialize(actor, mailbox)
      @actor, @mailbox = actor, mailbox
    end

    def send(meth, *args, &block)
      __call :send, meth, *args, &block
    end

    def respond_to?(meth)
      __call :respond_to?, meth
    end

    def methods(include_ancestors = true)
      __call :methods, include_ancestors
    end

    def alive?
      @actor.alive?
    end

    def to_s
      __call :to_s
    end

    def inspect
      return __call :inspect if alive?
      "#<Celluloid::Actor(#{@actor.class}:0x#{@actor.object_id.to_s(16)}) dead>"
    end

    # Create a Celluloid::Future which calls a given method
    def future(method_name, *args, &block)
      Celluloid::Future.new { __call method_name, *args, &block }
    end

    # Terminate the associated actor
    def terminate
      raise DeadActorError, "actor already terminated" unless alive?

      begin
        send :terminate
      rescue DeadActorError
        # In certain cases this is thrown during termination. This is likely
        # a bug in Celluloid's internals, but it shouldn't affect the caller.
        # FIXME: track this down and fix it, or at the very least log it
      end

      # Always return nil until a dependable exit value can be obtained
      nil
    end

    # method_missing black magic to call bang predicate methods asynchronously
    def method_missing(meth, *args, &block)
      # bang methods are async calls
      if meth.to_s.match(/!$/)
        unbanged_meth = meth.to_s.sub(/!$/, '')
        our_mailbox = Thread.current.mailbox

        begin
          @mailbox << AsyncCall.new(our_mailbox, unbanged_meth, args, block)
        rescue MailboxError
          # Silently swallow asynchronous calls to dead actors. There's no way
          # to reliably generate DeadActorErrors for async calls, so users of
          # async calls should find other ways to deal with actors dying
          # during an async call (i.e. linking/supervisors)
        end

        return # casts are async and return immediately
      end

      __call(meth, *args, &block)
    end

    #######
    private
    #######

    # Make a synchronous call to the actor we're proxying to
    def __call(meth, *args, &block)
      our_mailbox = Thread.current.mailbox
      call = SyncCall.new(our_mailbox, meth, args, block)

      begin
        @mailbox << call
      rescue MailboxError
        raise DeadActorError, "attempted to call a dead actor"
      end

      if Celluloid.actor?
        # Yield to the actor scheduler, which resumes us when we get a response
        response = Fiber.yield(call)
      else
        # Otherwise we're inside a normal thread, so block
        response = our_mailbox.receive do |msg|
          msg.is_a? Response and msg.call == call
        end
      end

      case response
      when SuccessResponse<commit_msg>This may be a bit more idiomatic<commit_after>module Celluloid
  # A proxy object returned from Celluloid::Actor.spawn/spawn_link which
  # dispatches calls and casts to normal Ruby objects which are running inside
  # of their own threads.
  class ActorProxy
    # FIXME: not nearly enough methods are delegated here
    attr_reader :mailbox

    def initialize(actor, mailbox)
      @actor, @mailbox = actor, mailbox
    end

    def send(meth, *args, &block)
      __call__ :send, meth, *args, &block
    end

    def respond_to?(meth)
      __call__ :respond_to?, meth
    end

    def methods(include_ancestors = true)
      __call__ :methods, include_ancestors
    end

    def alive?
      @actor.alive?
    end

    def to_s
      __call__ :to_s
    end

    def inspect
      return __call__ :inspect if alive?
      "#<Celluloid::Actor(#{@actor.class}:0x#{@actor.object_id.to_s(16)}) dead>"
    end

    # Create a Celluloid::Future which calls a given method
    def future(method_name, *args, &block)
      Celluloid::Future.new { __call__ method_name, *args, &block }
    end

    # Terminate the associated actor
    def terminate
      raise DeadActorError, "actor already terminated" unless alive?

      begin
        send :terminate
      rescue DeadActorError
        # In certain cases this is thrown during termination. This is likely
        # a bug in Celluloid's internals, but it shouldn't affect the caller.
        # FIXME: track this down and fix it, or at the very least log it
      end

      # Always return nil until a dependable exit value can be obtained
      nil
    end

    # method_missing black magic to call bang predicate methods asynchronously
    def method_missing(meth, *args, &block)
      # bang methods are async calls
      if meth.to_s.match(/!$/)
        unbanged_meth = meth.to_s.sub(/!$/, '')
        our_mailbox = Thread.current.mailbox

        begin
          @mailbox << AsyncCall.new(our_mailbox, unbanged_meth, args, block)
        rescue MailboxError
          # Silently swallow asynchronous calls to dead actors. There's no way
          # to reliably generate DeadActorErrors for async calls, so users of
          # async calls should find other ways to deal with actors dying
          # during an async call (i.e. linking/supervisors)
        end

        return # casts are async and return immediately
      end

      __call__(meth, *args, &block)
    end

    #######
    private
    #######

    # Make a synchronous call to the actor we're proxying to
    def __call__(meth, *args, &block)
      our_mailbox = Thread.current.mailbox
      call = SyncCall.new(our_mailbox, meth, args, block)

      begin
        @mailbox << call
      rescue MailboxError
        raise DeadActorError, "attempted to call a dead actor"
      end

      if Celluloid.actor?
        # Yield to the actor scheduler, which resumes us when we get a response
        response = Fiber.yield(call)
      else
        # Otherwise we're inside a normal thread, so block
        response = our_mailbox.receive do |msg|
          msg.is_a? Response and msg.call == call
        end
      end

      case response
      when SuccessResponse
{'fraction_non_alphanumeric': 0.0717106302321908, 'fraction_numerical': 0.000947717580161112, 'mean_word_length': 2.4357026587086272, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '215241', 'n_tokens_mistral': 1875, 'n_tokens_neox': 1775, 'n_words': 669}