NAME

UniEvent::Loop - waits and dispatches events for active handlers

SYNOPSIS

my $loop = UniEvent::Loop->new;
say "current unix epoch: ", $loop->now, " (milliseconds)";
$loop->delay(sub { say "executed before polling I/O" });
my $t = UniEvent::Timer->new($loop);
$t->once(0.05, sub { say "on_timer" });
$loop->run;  # exists as soon as there is nothing to do

DESCRIPTION

The event loop is the central part of functionality. It takes care of polling for i/o and scheduling callbacks to be run based on different sources of events.

Contrary to AnyEvent and EV, where there is only one event loop instance (singleton), with UniEvent it is possible to have many independent loops. The most close to the <AnyEvent> approach is, probably, the default loop in <UniEvent>; when a new handle (I/O event listener) is created, if the $loop parameter is ommited (or it is undefined), then the default loop is used.

Event loops are independent each from other. That means, for example, if there are two loop instances,

my $loop_1 = UniEvent::Loop->new;
my $loop_2 = UniEvent::Loop->new;
...;
$loop_1->run;

Only handles from $loop_1 will be polled for I/O.

Another noteable difference from the AnyEvent is that UniEvent event loop is not reenterant and leads to undefined behaviour. E.g.

my $cv = AE::cv;
...
my $t = AE::timer 0.1, 0, sub {
    say $cv->recv; # implicitely runs loop nested iteration
};
...

cannot be done with UniEvent; however, to our opinion the AE-approach in that case should be discouraged in production code, as it possibly leads to dead locks (or live locks), and might be allowed in tests only.

It is possible, however, to have something similar, i.e. switch from async mode, in synchronous within the scope of some function, e.g.

my $app_loop = UniEvent::Loop->new;
my $t = UniEvent::Timer->new($app_loop);
$t->once(0.05, sub {
   my $inner_loop = UniEvent::Loop->new;
   ... # add new handles
   $inner_loop->run;
});
$app_loop->run;

It should be noted that loop cannot be changed in handles, that's why it is possible to specify it in handle constructor only.

FUNCTIONS

global_loop()

global()

Returns global loop, which is a "per application singleton", i.e. it is the same loop instance for all application threads. It is rarely used from pure Perl, however can be used when something is happening on different threads using C++.

The loop is not thread safe, and it is application developer responsibility to manager synchronization.

default_loop()

default()

Returns per thread loop singleton. For many cases, when event loop parameter is ommited, the default loop is used.

METHODS

new([$backend = undef])

Constructs new event loop object using the specified backend. If the $backend is undef then the default backend is used, which is currently the UniEvent::Backend::UV.

is_default()

Returns true if the loop instance is the default loop (for the current thead).

is_global()

Returns true if the loop instance is the application global loop.

alive()

Returns true if there are active handles or requests in the loop.

now()

Return the current timestamp in milliseconds. The value is cached for each event loop tick. The timestamp is monotonically increased at arbitrary point of time.

update_time()

Updates cached "now" value for the loop. It is useful, if in a callback or handle there is a time-sensitive blocking I/O operation, where it is undesirable to let the following callbacks have outdated "now" value.

run()

Runs the event loop until there are no more active and referenced handles or requests. Returns true if the loop was stopped and there are more active requests or handles.

This is not reenterant method.

run_once()

Polls for I/O once and blocks if there are no pending callbacks. Returns true if more pending callbacks are expected, i.e. they will be invoked upon the next run_once invocation.

This is not reenterant method.

run_nowait()

Polls for I/O once and does not blocks if there are no pending callbacks. Returns true if pending callbacks are expected, i.e. they will be invoked upon the next run_nowait invocation.

This is not reenterant method.

stop()

Stop the event loop, causing run to end as soon as possible. This will happen not sooner than the next loop iteration. If this function was called before blocking for i/o, the loop won't block for i/o on this iteration.

handles()

Returns array of handles, associated with the loop.

delay($callback)

This is a convenient one-shot callback, which will be invoked "a little bit later", similar to UniEvent::Idle. "A little bit later" is somewhat unspecified, but normally it is on the next loop iteration; although, it might be invoked don't waiting the next iteration.

In non-void context it returns the delay cancellation guard. In void context the provided callback is non-cancellable.

The callback can be cancelled either via undef'ing $guard or via calling the cancel_delay.

my $guard = $loop->delay(sub { say 'hello' });
$guard = undef if ($some_condition);
$loop->run;

cancel_delay($delay_guard)

Cancels previously set delay.

fork_event()

Returns XS::Framework::CallbackDispatcher instance, where callback(s) can be assigned with. The callbacks will be invoked after fork(2) syscall in the child process.

The C++ interface is:

void(const LoopSP&);

i.e. the callback returns nothing and as an argument takes event loop instance.

Multiple callbacks can be added via the XS::Framework::CallbackDispatcher interface.

After the fork it reinitializes event loop and its handlers. The method might be not available on some platforms (e.g. Windows) or have specifics in behaviour (e.g. FsEvent on Mac OS X).

You need to call the method in child process after fork only if it is planned to continue use the event loop instance. The assigned callbacks will be invoked before Loop::run.

This method is still considered unstable and experimental, so it is desirable spawn a new loop in a child process rather than reusing the old one from a parent process.

start_debug_tracer($callback)

This is debug assistant function. The $callback is always invoked upon new handle binding to the loop. It is expected that the $callback will return a scalar, which will be linked with the new handle. Later it can be examined via the watch_active_trace method.

The scalar can be arbitrary value, however, it is be the most useful if it is stacktrace, generated by modules like Exception::Backtrace or Devel::Trace.

watch_active_trace($callback)

Examines each active non-weakened handle for the attached scalar (backtrace). Meant to be used with start_debug_tracer. Example:

$loop->start_debug_tracer(sub { Exception::Backtrace::create_backtrace() });
...;
# somewhere inside any handler callback
$loop->watch_active_trace(sub {
    my ($handle, $trace) = @_;
    say "$handle ", $trace->to_string;
});
...;
$loop->run;

REFERENCES

UniEvent::Handle

UniEvent::Idle

XS::Framework::CallbackDispatcher