Module: IO::Event::Selector

Defined in:
lib/io/event/selector.rb,
lib/io/event/selector/select.rb,
lib/io/event/selector/nonblock.rb,
ext/io/event/event.c

Defined Under Namespace

Classes: EPoll, KQueue, Select, URing

Class Method Summary collapse

Class Method Details

.default(env = ENV) ⇒ Object

The default selector implementation, which is chosen based on the environment and available implementations.



21
22
23
24
25
26
27
# File 'lib/io/event/selector.rb', line 21

def self.default(env = ENV)
	if name = env["IO_EVENT_SELECTOR"]&.to_sym
		return const_get(name)
	else
		BEST
	end
end

.new(loop, env = ENV) ⇒ Object

Create a new selector instance, according to the best available implementation.



34
35
36
37
38
39
40
41
42
# File 'lib/io/event/selector.rb', line 34

def self.new(loop, env = ENV)
	selector = default(env).new(loop)
	
	if debug = env["IO_EVENT_DEBUG_SELECTOR"]
		selector = Debug::Selector.wrap(selector, env)
	end
	
	return selector
end

.nonblock(io) ⇒ Object

Execute the given block in non-blocking mode.



14
15
16
17
18
19
# File 'lib/io/event/selector/nonblock.rb', line 14

def self.nonblock(io, &block)
	io.nonblock(&block)
rescue Errno::EBADF
	# Windows.
	yield
end

.process_wait(pid, flags) ⇒ Object

Wait for a process to change state, for the cases a selector cannot represent natively (e.g. pid <= 0: any child, or a process group). The native selectors integrate process waiting with the event loop using per-process primitives (pidfd_open, EVFILT_PROC) which can only refer to a single, specific process, and delegate here otherwise.

The wait is performed on a separate thread, which has no fiber scheduler and therefore blocks. Joining it via Thread#value is fiber-scheduler aware, so the calling fiber yields to the event loop and the reactor keeps running other fibers.



51
52
53
54
55
56
57
58
59
60
# File 'lib/io/event/selector.rb', line 51

def self.process_wait(pid, flags)
	thread = ::Thread.new do
		::Process::Status.wait(pid, flags)
	end
	
	thread.value
ensure
	# If the calling fiber was interrupted before the wait completed, don't leave the thread running:
	thread&.kill
end