TABLE OF CONTENTS

NAME

Mojo::IOLoop - Minimalistic event loop

SYNOPSIS

use Mojo::IOLoop;

# Listen on port 3000
Mojo::IOLoop->server({port => 3000} => sub {
  my ($loop, $stream) = @_;

  $stream->on(read => sub {
    my ($stream, $bytes) = @_;

    # Process input chunk
    say $bytes;

    # Write response
    $stream->write('HTTP/1.1 200 OK');
  });
});

# Connect to port 3000
my $id = Mojo::IOLoop->client({port => 3000} => sub {
  my ($loop, $err, $stream) = @_;

  $stream->on(read => sub {
    my ($stream, $bytes) = @_;

    # Process input
    say "Input: $bytes";
  });

  # Write request
  $stream->write("GET / HTTP/1.1\x0d\x0a\x0d\x0a");
});

# Add a timer
Mojo::IOLoop->timer(5 => sub {
  my $loop = shift;
  $loop->remove($id);
});

# Start event loop if necessary
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

DESCRIPTION

Mojo::IOLoop is a very minimalistic event loop based on Mojo::Reactor, it has been reduced to the absolute minimal feature set required to build solid and scalable non-blocking TCP clients and servers.

Optional modules EV (4.0+), IO::Socket::IP (0.16+) and IO::Socket::SSL (1.75+) are supported transparently, and used if installed. Individual features can also be disabled with the MOJO_NO_IPV6 and MOJO_NO_TLS environment variables.

The event loop will be resilient to time jumps if a monotonic clock is available through Time::HiRes. A TLS certificate and key are also built right in, to make writing test servers as easy as possible. Also note that for convenience the PIPE signal will be set to IGNORE when Mojo::IOLoop is loaded.

See Mojolicious::Guides::Cookbook for more.

ATTRIBUTES

Mojo::IOLoop 实现了下列的属性

accept_interval

my $interval = $loop->accept_interval;
$loop        = $loop->accept_interval(0.5);

试图重新获得接受互斥的间隔, 以秒为单位, 默认为 0.025。需要注意的是改变这个值会影响性能和使用空闲的 CPU。

lock

my $cb = $loop->lock;
$loop  = $loop->lock(sub {...});

获得接受互斥的回调,用于同步多个服务器进程。回调应该返回true或false。请注意,在这个回调的异常不捕获。

$loop->lock(sub {
  my ($loop, $blocking) = @_;

  # Got the accept mutex, start accepting new connections
  return 1;
});

max_accepts

my $max = $loop->max_accepts;
$loop   = $loop->max_accepts(1000);

在不中断现有连接的情况下,可以接收的最大的事件循环, 超过会直接关掉,默认为 0. 将该值设置 0 会让此事件循环无止境地接受新的连接 Note that up to half of this value can be subtracted randomly to improve load balancing between multiple server processes.

max_connections

my $max = $loop->max_connections;
$loop   = $loop->max_connections(1000);

这是事件循环所能处理的并行的连接最大数量, 在这个数目之前都能接收新的连接.

multi_accept

my $multi = $loop->multi_accept;
$loop     = $loop->multi_accept(100);

一次所能接收的连接数,默认为 50.

reactor

my $reactor = $loop->reactor;
$loop       = $loop->reactor(Mojo::Reactor->new);

低级别的事件反应堆(reactor),通常是 Mojo::Reactor::Poll 要么是 Mojo::Reactor::EV 的对象.

# 等着句柄如果可读或可写
$loop->reactor->io($handle => sub {
  my ($reactor, $writable) = @_;
  say $writable ? 'Handle is writable' : 'Handle is readable';
});

# 改变监控只有当句柄可读的时候
$loop->reactor->watch($handle, 0, 1);

unlock

my $cb = $loop->unlock;
$loop  = $loop->unlock(sub {...});

这个用于回调放开互斥锁,用于同步多个服务器的进程,注意,这时回调的异常是不能捕获到的.

METHODS

Mojo::IOLoop inherits all methods from Mojo::Base and implements the following new ones.

acceptor

my $server = Mojo::IOLoop->acceptor($id);
my $server = $loop->acceptor($id);
my $id     = $loop->acceptor(Mojo::IOLoop::Server->new);

Get Mojo::IOLoop::Server object for id or turn object into an acceptor.

client

my $id
  = Mojo::IOLoop->client(address => '127.0.0.1', port => 3000, sub {...});
my $id = $loop->client(address => '127.0.0.1', port => 3000, sub {...});
my $id = $loop->client({address => '127.0.0.1', port => 3000} => sub {...});

Open TCP connection with Mojo::IOLoop::Client, takes the same arguments as "connect" in Mojo::IOLoop::Client.

# Connect to localhost on port 3000
Mojo::IOLoop->client({port => 3000} => sub {
  my ($loop, $err, $stream) = @_;
  ...
});

delay

my $delay = Mojo::IOLoop->delay;
my $delay = $loop->delay;
my $delay = $loop->delay(sub {...});
my $delay = $loop->delay(sub {...}, sub {...});

Get Mojo::IOLoop::Delay object to manage callbacks and control the flow of events. A single callback will be treated as a subscriber to the finish event, and multiple ones as a chain of steps.

# Synchronize multiple events
my $delay = Mojo::IOLoop->delay(sub { say 'BOOM!' });
for my $i (1 .. 10) {
  my $end = $delay->begin;
  Mojo::IOLoop->timer($i => sub {
    say 10 - $i;
    $end->();
  });
}

# Sequentialize multiple events
my $delay = Mojo::IOLoop->delay(

  # First step (simple timer)
  sub {
    my $delay = shift;
    Mojo::IOLoop->timer(2 => $delay->begin);
    say 'Second step in 2 seconds.';
  },

  # Second step (parallel timers)
  sub {
    my $delay = shift;
    Mojo::IOLoop->timer(1 => $delay->begin);
    Mojo::IOLoop->timer(3 => $delay->begin);
    say 'Third step in 3 seconds.';
  },

  # Third step (the end)
  sub { say 'And done after 5 seconds total.' }
);

# Wait for events if necessary
$delay->wait unless Mojo::IOLoop->is_running;

generate_port

my $port = Mojo::IOLoop->generate_port;
my $port = $loop->generate_port;

Find a free TCP port, this is a utility function primarily used for tests.

is_running

my $success = Mojo::IOLoop->is_running;
my $success = $loop->is_running;

Check if event loop is running.

exit unless Mojo::IOLoop->is_running;

one_tick

Mojo::IOLoop->one_tick;
$loop->one_tick;

运行事件循环直到事件发生. 注意, 此方法可以递归回到 reactor, 所以你必须要小心.

recurring

my $id = Mojo::IOLoop->recurring(0.5 => sub {...});
my $id = $loop->recurring(3 => sub {...});

Create a new recurring timer, invoking the callback repeatedly after a given amount of time in seconds.

# Invoke as soon as possible
Mojo::IOLoop->recurring(0 => sub { say 'Reactor tick.' });

remove

Mojo::IOLoop->remove($id);
$loop->remove($id);

Remove anything with an id, connections will be dropped gracefully by allowing them to finish writing all data in their write buffers.

server

my $id = Mojo::IOLoop->server(port => 3000, sub {...});
my $id = $loop->server(port => 3000, sub {...});
my $id = $loop->server({port => 3000} => sub {...});

Accept TCP connections with Mojo::IOLoop::Server, takes the same arguments as "listen" in Mojo::IOLoop::Server.

# Listen on port 3000
Mojo::IOLoop->server({port => 3000} => sub {
  my ($loop, $stream, $id) = @_;
  ...
});

singleton

my $loop = Mojo::IOLoop->singleton;

全局的 Mojo::IOLoop 一个唯一实例, 在进程的内部各处都是使用它来访问共享的单独的事件循环.

# Many methods also allow you to take shortcuts
Mojo::IOLoop->timer(2 => sub { Mojo::IOLoop->stop });
Mojo::IOLoop->start;

# Restart active timer
my $id = Mojo::IOLoop->timer(3 => sub { say 'Timeout!' });
Mojo::IOLoop->singleton->reactor->again($id);

start

Mojo::IOLoop->start;
$loop->start;

开始事件循环, 这将会阻塞直接到 stop 被调用的时候. 注意如果没有事件需要 watch 的时候, 有些 reactor 就会自动的停止.

# Start event loop only if it is not running already
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

stop

Mojo::IOLoop->stop;
$loop->stop;

停止事件循环, 这将不会中断现有的连接和事件循环可以通过运行 start 再次被重新启动。

stream

my $stream = Mojo::IOLoop->stream($id);
my $stream = $loop->stream($id);
my $id     = $loop->stream(Mojo::IOLoop::Stream->new);

Get Mojo::IOLoop::Stream object for id or turn object into a connection.

# Increase inactivity timeout for connection to 300 seconds
Mojo::IOLoop->stream($id)->timeout(300);

timer

my $id = Mojo::IOLoop->timer(5 => sub {...});
my $id = $loop->timer(5 => sub {...});
my $id = $loop->timer(0.25 => sub {...});

创建一个 timer, 在那个给定的总时间之后调用这个回调.

# Invoke as soon as possible
Mojo::IOLoop->timer(0 => sub { say 'Next tick.' });

DEBUGGING

如果你设置了 MOJO_IOLOOP_DEBUG 的环境变量, 会给高级的诊断信息打印到标准错误.

MOJO_IOLOOP_DEBUG=1

SEE ALSO

Mojolicious, Mojolicious::Guides, http://mojolicio.us.