NAME

UniEvent::Loop - The event loop object

SYNOPSIS

my $loop = UniEvent::Loop->new;

my $timer = UE::timer 1, sub { ... }, $loop;

$loop->run; # exists as soon as there is nothing to do

$loop->delay(sub { say "executed once. soon, but not now" });

$loop->update_time;
say "current unix epoch: ", $loop->now, " (milliseconds)";

DESCRIPTION

The event loop is the central part of UniEvent's 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 $loop1 = UniEvent::Loop->new;
my $loop2 = UniEvent::Loop->new;
...;
$loop1->run;

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

It should be noted that handles can't be transferred between different loops. That's why it is possible to specify it in handle constructor only.

FUNCTIONS

default(), ALIAS default_loop()

global(), ALIAS global_loop()

Returns a singleton loop object.

The only difference between default() and global() can be noted on threaded perls in case if you use multiple threads in your application. default() loop is thread-local, i.e. it a singleton, but it is different in each thread; while global() loop is the same loop instance for the whole application.

global() always returns main thread's default() loop.

It is not recommended to use global(), because loop objects are not thread-safe and thus using global() may lead to undefined behaviour if used from different threads. It exists only for rare cases when you definitely know what you're doing.

For many cases, when event loop parameter is ommited, the default() loop is used.

NOTE: for single-threaded applications, global() and default() returns the same loop object.

METHODS

new([$backend = default])

Constructs new event loop object using the specified backend. If the $backend is not specified, then the default backend is used.

See "default_backend()" in UniEvent

is_default()

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

is_global()

Returns true if the loop 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 iteration. 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 still active handles or requests.

This method MAY be non-reenterant, i.e. must not be called from an event callback, as many backends does not support recursive run.

run_once()

Poll for i/o once (may block until there are pending callbacks). Returns false when done (no active handles or requests left), or true if more callbacks are expected (meaning you should run the event loop again sometime in the future).

This method MAY be non-reenterant, i.e. must not be called from an event callback, as many backends does not support recursive run.

run_nowait()

Poll for i/o once but don’t block if there are no pending callbacks. Returns false if done (no active handles or requests left), or true if more callbacks are expected (meaning you should run the event loop again sometime in the future).

This method MAY be non-reenterant, i.e. must not be called from an event callback, as many backends does not support recursive run.

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.

It is recommended for use only for debugging.

delay($callback)

This is a convenient one-shot callback, which will be invoked "a little bit later". "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. It is guaranteed that callback will not be called until we return from the current callback code flow (return to the loop internal code).

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 cancel_delay method.

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

cancel_delay($delay_guard)

Cancels previously set delay. Does nothing if it's too late (callback has already been called).

fork_event()

Returns XS::Framework::CallbackDispatcher for setting callback which will be invoked when the application fork()s.

See "EVENT CALLBACKS" in UniEvent for more info.

Callback is called on behalf of a child process, after all fork-related work for event loop is done (see "FORK" in UniEvent).

The callback will receive single argument - the event loop object.

$loop->fork_event->add(sub {
    my $loop = shift;
    ...
});

resolver()

Returns per-loop UniEvent::Resolver object.

This resolver object does not hold the loop, so if you keep a reference to it, you must not use it after it's loop death (otherwise exception will be thrown).

track_load_average($seconds)

Starts tracking load average on the loop. Tracked value is the average loop busy load for last $seconds. This value is NOT a CPU load, instead it is somewhat more useful. It is wallclock time that was spent on calling user callbacks (and related stuff) during last $seconds divided by $seconds. I.e. part of the time, the loop was not in I/O polling, in other words, part of the time the loop was busy and could not receive new events.

This value is more useful than CPU load because even in case of blocking code (waiting for blocking I/O) it will count such time as busy time.

get_load_average()

Returns loop busy load (value between 0 and 1, where 1 means 100% busy). If track_load_average() wasn't previously enabled, returns 0.

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 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;

CAVEATS

Notable 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; # implicitly runs loop nested iteration
};
...

cannot be done with UniEvent. The limitation is imposed by libuv event loop. This might be changed in future for other backends that support such feature. 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.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 127:

Non-ASCII character seen before =encoding in 'don’t'. Assuming UTF-8