File: receivers.rb

package info (click to toggle)
ruby-celluloid 0.18.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 848 kB
  • sloc: ruby: 7,579; makefile: 10
file content (64 lines) | stat: -rw-r--r-- 1,469 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
require "set"
require "timers"

module Celluloid
  module Internals
    # Allow methods to directly interact with the actor protocol
    class Receivers
      def initialize(timers)
        @receivers = Set.new
        @timers = timers
      end

      # Receive an asynchronous message
      def receive(timeout = nil, &block)
        if Celluloid.exclusive?
          Celluloid.mailbox.receive(timeout, &block)
        else
          receiver = Receiver.new block

          if timeout
            receiver.timer = @timers.after(timeout) do
              @receivers.delete receiver
              receiver.resume
            end
          end

          @receivers << receiver
          Task.suspend :receiving
        end
      end

      # Handle incoming messages
      def handle_message(message)
        receiver = @receivers.find { |r| r.match(message) }
        return unless receiver

        @receivers.delete receiver
        receiver.timer.cancel if receiver.timer
        receiver.resume message
        message
      end
    end

    # Methods blocking on a call to receive
    class Receiver
      attr_accessor :timer

      def initialize(block)
        @block = block
        @task  = Task.current
        @timer = nil
      end

      # Match a message with this receiver's block
      def match(message)
        @block ? @block.call(message) : true
      end

      def resume(message = nil)
        @task.resume message
      end
    end
  end
end