class Coolio::Loop

Constants

EVBACKEND_EPOLL
EVBACKEND_KQUEUE
EVBACKEND_POLL
EVBACKEND_PORT
EVBACKEND_SELECT
EVFLAG_FORKCHECK
EVFLAG_NOENV

Public Class Methods

default() click to toggle source

Retrieve the default event loop for the current thread

# File lib/cool.io/loop.rb, line 19
def self.default
  Thread.current._coolio_loop
end
new(options = {}) click to toggle source

Create a new Coolio::Loop

Options:

:skip_environment (boolean)

Ignore the $LIBEV_FLAGS environment variable

:fork_check (boolean)

Enable autodetection of forks

:backend

Choose the default backend, one (or many in an array) of:
  :select (most platforms)
  :poll   (most platforms except Windows)
  :epoll  (Linux)
  :kqueue (BSD/Mac OS X)
  :port   (Solaris 10)
# File lib/cool.io/loop.rb, line 41
def initialize(options = {})
  @watchers = {}
  @active_watchers = 0

  flags = 0

  options.each do |option, value|
    case option
    when :skip_environment
      flags |= EVFLAG_NOEV if value
    when :fork_check
      flags |= EVFLAG_FORKCHECK if value
    when :backend
      value = [value] unless value.is_a? Array
      value.each do |backend|
        case backend
        when :select then flags |= EVBACKEND_SELECT
        when :poll   then flags |= EVBACKEND_POLL
        when :epoll  then flags |= EVBACKEND_EPOLL
        when :kqueue then flags |= EVBACKEND_KQUEUE
        when :port   then flags |= EVBACKEND_PORT
        else raise ArgumentError, "no such backend: #{backend}"
        end
      end
    else raise ArgumentError, "no such option: #{option}"
    end
  end

  @loop = ev_loop_new(flags)
end

Public Instance Methods

attach(watcher) click to toggle source

Attach a watcher to the loop

# File lib/cool.io/loop.rb, line 73
def attach(watcher)
  watcher.attach self
end
has_active_watchers?() click to toggle source

Does the loop have any active watchers?

# File lib/cool.io/loop.rb, line 100
def has_active_watchers?
  @active_watchers > 0
end
run(timeout = nil) click to toggle source

Run the event loop and dispatch events back to Ruby. If there are no watchers associated with the event loop it will return immediately. Otherwise, run will continue blocking and making event callbacks to watchers until all watchers associated with the loop have been disabled or detached. The loop may be explicitly stopped by calling the stop method on the loop object.

# File lib/cool.io/loop.rb, line 83
def run(timeout = nil)
  raise RuntimeError, "no watchers for this loop" if @watchers.empty?

  @running = true
  while @running and not @active_watchers.zero?
    run_once(timeout)
  end
  @running = false
end
Coolio::Loop.run_nonblock → nil click to toggle source

Run the Coolio::Loop once, but return immediately if there are no pending events.

static VALUE Coolio_Loop_run_nonblock(VALUE self)
{
  struct Coolio_Loop *loop_data;
  VALUE nevents;
  
  Data_Get_Struct(self, struct Coolio_Loop, loop_data);

  assert(loop_data->ev_loop && !loop_data->events_received);

  RUN_LOOP(loop_data, EVLOOP_NONBLOCK);  
  Coolio_Loop_dispatch_events(loop_data);
  
  nevents = INT2NUM(loop_data->events_received);
  loop_data->events_received = 0;
  
  return nevents;
}
Coolio::Loop.run_once → nil click to toggle source

Run the Coolio::Loop once, blocking until events are received.

static VALUE Coolio_Loop_run_once(int argc, VALUE *argv, VALUE self)
{
  VALUE timeout;
  VALUE nevents;
  struct Coolio_Loop *loop_data;

  rb_scan_args(argc, argv, "01", &timeout);

  if (timeout != Qnil && NUM2DBL(timeout) < 0) {
    rb_raise(rb_eArgError, "time interval must be positive");
  }

  Data_Get_Struct(self, struct Coolio_Loop, loop_data);

  assert(loop_data->ev_loop && !loop_data->events_received);

  /* Implement the optional timeout (if any) as a ev_timer */
  /* Using the technique written at
     http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#code_ev_timer_code_relative_and_opti,
     the timer is not stopped/started everytime when timeout is specified, instead,
     the timer is stopped when timeout is not specified. */
  if (timeout != Qnil) {
    /* It seems libev is not a fan of timers being zero, so fudge a little */
    loop_data->timer.repeat = NUM2DBL(timeout) + 0.0001;
    ev_timer_again(loop_data->ev_loop, &loop_data->timer);
  } else {
    ev_timer_stop(loop_data->ev_loop, &loop_data->timer);
  }

  /* libev is patched to release the GIL when it makes its system call */
  RUN_LOOP(loop_data, EVLOOP_ONESHOT);

  Coolio_Loop_dispatch_events(loop_data);
  nevents = INT2NUM(loop_data->events_received);
  loop_data->events_received = 0;

  return nevents;
}
stop() click to toggle source

Stop the event loop if it’s running

# File lib/cool.io/loop.rb, line 94
def stop
  raise RuntimeError, "loop not running" unless @running
  @running = false
end
watchers() click to toggle source

All watchers attached to the current loop

# File lib/cool.io/loop.rb, line 105
def watchers
  @watchers.keys
end

Private Instance Methods

ev_loop_new(p1) click to toggle source

Wrapper for populating a Coolio_Loop struct with a new event loop

static VALUE Coolio_Loop_ev_loop_new(VALUE self, VALUE flags)
{
  struct Coolio_Loop *loop_data;
  Data_Get_Struct(self, struct Coolio_Loop, loop_data);

  if(loop_data->ev_loop)
    rb_raise(rb_eRuntimeError, "loop already initialized");

  loop_data->ev_loop = ev_loop_new(NUM2INT(flags));

  return Qnil;
}