Class: RBus::Mainloop

Inherits:
Object
  • Object
show all
Includes:
MonitorMixin, Observable
Defined in:
lib/rbus/mainloop/glib.rb,
lib/rbus/mainloop/thread.rb,
lib/rbus/mainloop/mainloop.rb

Instance Method Summary collapse

Constructor Details

#initialize(bus) ⇒ Mainloop

Returns a new instance of Mainloop.



33
34
35
36
37
38
39
40
# File 'lib/rbus/mainloop/mainloop.rb', line 33

def initialize(bus)
  super()
  @bus = bus
  @transport = @bus.transport
  @writer = Message::Writer.new(@transport)
  @reader = Message::Reader.new(@transport)
  setup
end

Instance Method Details

#handle_incoming(message) ⇒ Object

Mainloop implementations should call this method with any message received from the Bus. Handles nil messages for non-blocking loops.



51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/rbus/mainloop/mainloop.rb', line 51

def handle_incoming(message)
  return if message.nil?
  
  # - names.nil? is when Bus is connecting only
  # - destination.empty? is for signals only
  # - otherwise, names must include the destination
  return unless @bus.names.nil? || message.destination.nil? || @bus.names.include?(message.destination)
  
  # The audience is listening... broadcast the new message.
  changed
  notify_observers(message)
end

#handle_outgoing(message) ⇒ Object

Mainloop implementations should call this method with any message to be sent to the Bus, and a callback, if available. Returns appropriate observer



67
68
69
70
71
72
# File 'lib/rbus/mainloop/mainloop.rb', line 67

def handle_outgoing(message)      
  # Make sure only one message is sent at each time.  
  synchronize do
    @writer.send_message(message)
  end
end

#notify_observers(*arg) ⇒ Object

Threaded version of observable’s method with same name.



40
41
42
43
44
45
46
47
48
49
# File 'lib/rbus/mainloop/thread.rb', line 40

def notify_observers(*arg) # :nodoc:
  if defined? @observer_state and @observer_state
    if defined? @observer_peers
      for i in @observer_peers.dup
        Thread.new{i.update(*arg)}
      end
    end
    @observer_state = false
  end
end

#send_message(message, callback = nil) ⇒ Object

Send message, tell loop to expect an answer. Overridden by implementations.



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
# File 'lib/rbus/mainloop/mainloop.rb', line 76

def send_message(message, callback = nil)
  # TODO: if message has no_reply, use dummy observer
  if message.member == 'AddMatch'
    observer = SignalObserver.new(self, message.arguments[0], callback)
    message.arguments = message.arguments[0].map{|key,value|"#{key}='#{value}'"}.join(',')
  elsif callback
    observer = AsyncObserver.new(self, message.serial, callback)
  else
    observer = nil
  end
  
  handle_outgoing(message)

  # Handle sync reply right here.
  if observer.nil?
    @active = false  
    loop do
      reply = @reader.read_message
      next if reply.nil?
      if message.serial == reply.serial
        @active = true
        return reply.arguments
      else
        handle_incoming(reply)
        Gtk.main_iteration_do(false)
      end
    end
  end
end

#setupObject

Mainloop implementations should override this method to setup everything they need.



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/rbus/mainloop/mainloop.rb', line 44

def setup
  @active = true
  @io_channel = GLib::IOChannel.new(@transport.socket.fileno)
  @io_channel.add_watch(GLib::IOChannel::IN) do |ch, con|
    if @active
      message = @reader.read_message
      handle_incoming(message)
    end
    true
  end
end