Class: SFML::Network::SocketSelector

Inherits:
Object
  • Object
show all
Defined in:
lib/sfml/network/socket_selector.rb

Overview

Multiplex many sockets onto a single blocking #wait. Useful for one-thread network servers — register every socket / listener you care about, call #wait, then ask each one whether it's ready?. Ready means there's data to read or, for a listener, an incoming connection waiting.

selector = SFML::Network::SocketSelector.new
selector.add(listener)
clients.each { |c| selector.add(c) }

if selector.wait(timeout: 1.0)
if selector.ready?(listener)
  # accept() will not block
end
clients.each do |c|
  next unless selector.ready?(c)
  # receive() will return data
end
end

Ruby's IO.select covers a similar use case for plain Ruby IO objects; this binding exists for game code that's already using SFML::Network::Tcp{Socket,Listener} / UdpSocket.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize ⇒ SocketSelector

Create an empty selector. Use #add to register sockets.

Raises:



28
29
30
31
32
33
# File 'lib/sfml/network/socket_selector.rb', line 28

def initialize
  ptr = C::Network.sfSocketSelector_create
  raise NetworkError, "sfSocketSelector_create returned NULL" if ptr.null?

  @handle = FFI::AutoPointer.new(ptr, C::Network.method(:sfSocketSelector_destroy))
end

Instance Attribute Details

#handle ⇒ Object (readonly)

:nodoc:



96
97
98
# File 'lib/sfml/network/socket_selector.rb', line 96

def handle
  @handle
end

Instance Method Details

#add(socket) ⇒ Object

Register a TcpListener, TcpSocket, or UdpSocket for monitoring. Chainable.



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/sfml/network/socket_selector.rb', line 37

def add(socket)
  case socket
  when TcpListener then C::Network.sfSocketSelector_addTcpListener(@handle, socket.handle)
  when TcpSocket   then C::Network.sfSocketSelector_addTcpSocket(@handle,  socket.handle)
  when UdpSocket   then C::Network.sfSocketSelector_addUdpSocket(@handle,  socket.handle)
  else
    raise ArgumentError,
          "SocketSelector#add expects TcpListener, TcpSocket, or UdpSocket (got #{socket.class})"
  end
  self
end

#clear ⇒ Object

Unregister all sockets.



63
64
65
66
# File 'lib/sfml/network/socket_selector.rb', line 63

def clear
  C::Network.sfSocketSelector_clear(@handle)
  self
end

#ready?(socket) ⇒ Boolean

true if ready.

Returns:

  • (Boolean)


85
86
87
88
89
90
91
92
93
94
# File 'lib/sfml/network/socket_selector.rb', line 85

def ready?(socket)
  case socket
  when TcpListener then C::Network.sfSocketSelector_isTcpListenerReady(@handle, socket.handle)
  when TcpSocket   then C::Network.sfSocketSelector_isTcpSocketReady(@handle,  socket.handle)
  when UdpSocket   then C::Network.sfSocketSelector_isUdpSocketReady(@handle,  socket.handle)
  else
    raise ArgumentError,
          "SocketSelector#ready? expects TcpListener, TcpSocket, or UdpSocket (got #{socket.class})"
  end
end

#remove(socket) ⇒ Object

Stop monitoring a previously-added socket. Chainable.



50
51
52
53
54
55
56
57
58
59
60
# File 'lib/sfml/network/socket_selector.rb', line 50

def remove(socket)
  case socket
  when TcpListener then C::Network.sfSocketSelector_removeTcpListener(@handle, socket.handle)
  when TcpSocket   then C::Network.sfSocketSelector_removeTcpSocket(@handle,  socket.handle)
  when UdpSocket   then C::Network.sfSocketSelector_removeUdpSocket(@handle,  socket.handle)
  else
    raise ArgumentError,
          "SocketSelector#remove expects TcpListener, TcpSocket, or UdpSocket (got #{socket.class})"
  end
  self
end

#wait(timeout: nil) ⇒ Object

Block until at least one registered socket has activity, or timeout elapses. timeout may be a SFML::Time, a Numeric (seconds), or nil / SFML::Time.zero (no timeout — block forever). Returns true if a socket is ready, false on timeout.



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/sfml/network/socket_selector.rb', line 72

def wait(timeout: nil)
  t =
    case timeout
    when nil     then SFML::Time.zero
    when Time    then timeout
    when Numeric then SFML::Time.seconds(timeout.to_f)
    else
      raise ArgumentError, "timeout must be SFML::Time, Numeric, or nil"
    end
  C::Network.sfSocketSelector_wait(@handle, t.to_native)
end