File: system_events.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 (126 lines) | stat: -rw-r--r-- 3,130 bytes parent folder | download
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
module Celluloid
  class Actor
    # Handle high-priority system event messages
    def handle_system_event(event)
      if handler = SystemEvent.handle(event.class)
        send(handler, event)
      else
        # !!! DO NOT INTRODUCE ADDITIONAL GLOBAL VARIABLES !!!
        # rubocop:disable Style/GlobalVars
        Internals::Logger.debug "Discarded message (unhandled): #{message}" if $CELLULOID_DEBUG
        # rubocop:enable Style/GlobalVars
      end
    end
  end
  # High-priority internal system events
  class SystemEvent
    class << self
      @@system_events = {}
      def handle(type)
        @@system_events[type]
      end

      def handler(&block)
        raise ArgumentError, "SystemEvent handlers must be defined with a block." unless block
        method = begin
          handler = name
                    .split("::").last
                    .gsub(/([A-Z]+)([A-Z][a-z])/, "\1_\2")
                    .gsub(/([a-z\d])([A-Z])/, "\1_\2")
                    .tr("-", "_")
                    .downcase
          :"handle_#{handler}"
        end
        Actor.send(:define_method, method, &block)
        @@system_events[self] = method
      end
    end

    class LinkingEvent < SystemEvent
      # Shared initializer for LinkingRequest and LinkingResponse
      def initialize(actor, type)
        @actor = actor
        @type = type.to_sym
        raise ArgumentError, "type must be link or unlink" unless %i[link unlink].include?(@type)
      end
    end
  end

  # Request to link with another actor
  class LinkingRequest < SystemEvent::LinkingEvent
    attr_reader :actor, :type

    handler do |event|
      event.process(links)
    end

    def process(links)
      case type
      when :link   then links << actor
      when :unlink then links.delete actor
      end

      actor.mailbox << LinkingResponse.new(Actor.current, type)
    end
  end

  # Response to a link request
  class LinkingResponse < SystemEvent::LinkingEvent
    attr_reader :actor, :type
  end

  # An actor has exited for the given reason
  class ExitEvent < SystemEvent
    attr_reader :actor, :reason

    handler do |event|
      @links.delete event.actor
      @exit_handler.call(event)
    end

    def initialize(actor, reason = nil)
      @actor = actor
      @reason = reason
    end
  end

  # Name an actor at the time it's registered
  class NamingRequest < SystemEvent
    attr_reader :name

    handler do |event|
      @name = event.name

      # !!! DO NOT INTRODUCE ADDITIONAL GLOBAL VARIABLES !!!
      # rubocop:disable Style/GlobalVars
      Celluloid::Probe.actor_named(self) if $CELLULOID_MONITORING
      # rubocop:enable Style/GlobalVars
    end

    def initialize(name)
      @name = name
    end
  end

  # Request for an actor to terminate
  class TerminationRequest < SystemEvent
    handler do |_event|
      terminate
    end
  end

  # Signal a condition
  class SignalConditionRequest < SystemEvent
    def initialize(task, value)
      @task = task
      @value = value
    end
    attr_reader :task, :value

    handler(&:call)

    def call
      @task.resume(@value)
    end
  end
end