UV::Loop - Looping with libuv


  #!/usr/bin/env perl
  use strict;
  use warnings;

  use UV;

  # A new, non-default loop
  my $loop = UV::Loop->new();

  # a new loop with the walk callback provided:
  my $loop = UV::Loop->new(
    on_walk => sub {say "walking!"},

  # A new default loop instance (Singleton)
  my $loop = UV::Loop->default_loop(); # singleton constructor
  my $loop = UV::Loop->default(); # singleton constructor

  # run a loop with one of three options:
  $loop->run(); # runs with UV_RUN_DEFAULT
  $loop->run(UV::Loop::UV_RUN_DEFAULT); # explicitly state UV_RUN_DEFAULT


This module provides an interface to libuv's loop. We will try to document things here as best as we can, but we also suggest you look at the libuv docs directly for more details on how things work.

Event loops that work properly on all platforms. YAY!










UV::Loop makes the following extra events available.


    $loop->on("walk", sub { say "We are walking!"});
    $loop->on("walk", sub {
        # the handle instance this event fired on and the buffer size in use
        my ($handle) = @_;
        say "walking over active handles";

The walk callback fires when a $loop->walk() method gets called.


UV::Loop makes the following methods available.


    my $loop = UV::Loop->new(
        on_walk => sub {say "walking!"},
    my $default_loop = UV::Loop->default_loop();
    my $default_loop = UV::Loop->default();

This constructor either returns the default loop (singleton object), or creates a new event loop and initializes it.

Please look at the documentation from libuv.


    my $int = $loop->alive();

The alive method returns a non-zero value if there are active handles or requests in the loop.


    my $int = $loop->backend_fd();

The backend_fd method returns the backend file descriptor. Only kqueue, epoll and event ports are supported.

This can be used in conjunction with "run" in UV::Loop and UV_RUN_NOWAIT to poll in one thread and run the event loop's callbacks in another.

* Note: Embedding a kqueue fd in another kqueue pollset doesn't work on all platforms. It's not an error to add the fd but it never generates events.


    my $int = $loop->backend_timeout();

The backend_timeout method returns the poll timeout. The return value is in milliseconds, or -1 for no timeout.



The close method releases all internal loop resources. Call this method only when the loop has finished executing and all open handles and requests have been closed, or it will return UV::UV_EBUSY. After this method returns, the user can free the memory allocated for the loop.


    my $int = $loop->configure();

The configure method sets additional loop options. You should normally call this before the first call to "run" in UV::Loop unless mentioned otherwise.

Returns 0 on success or a UV/"CONSTANTS" error code on failure. Be prepared to handle UV::UV_ENOSYS; it means the loop option is not supported by the platform.

Supported options:

  • UV_LOOP_BLOCK_SIGNAL: Block a signal when polling for new events. The second argument to $loop->configure is the signal number.

    This operation is currently only implemented for SIGPROF signals, to suppress unnecessary wakeups when using a sampling profiler. Requesting other signals will fail with UV::UV_EINVAL.


    # this is a singleton constructor. you'll get the same instance each time
    my $default_loop = UV::Loop->default();

A singleton method to get the default loop instance.


    # this is a singleton constructor. you'll get the same instance each time
    my $default_loop = UV::Loop->default_loop();

A singleton method to get the default loop instance.


    # lets us know if this loop is the default loop for this context
    my $bool = $loop->is_default();

A read-only method to let us know if we're dealing with the default loop.


    my $uint64_t = $loop->now();

The now method returns the current timestamp in milliseconds. The timestamp is cached at the start of the event loop tick, see "update_loop" in UV::Loop for details and rationale.

The timestamp increases monotonically from some arbitrary point in time. Don't make assumptions about the starting point, you will only get disappointed.

* Note: Use "hrtime" in UV if you need sub-millisecond granularity.


    # set a walk event callback to print the handle's data attribute
    $loop->on('walk', sub {
        my $hndl = shift;
        say $hndl->data();
        say "walking!"

    # clear out the walk event callback for the loop
    $loop->on(walk => undef);
    $loop->on(walk => sub {});

The on method allows you to subscribe to "EVENTS" in UV::Loop emitted by any UV::Loop.


    # use UV_RUN_DEFAULT by default
    my $int = $loop->run();
    # or, explicitly use it:
    my $int = $loop->run(UV::Loop::UV_RUN_DEFAULT);
    # run in UV_RUN_NOWAIT mode
    my $int = $loop->run(UV::Loop::UV_RUN_NOWAIT);
    # run in UV_RUN_ONCE mode
    my $int = $loop->run(UV::Loop::UV_RUN_ONCE);

The run method runs the event loop. It will act differently depending on the specified mode:

  • UV_RUN_DEFAULT Runs the event loop until there are no more active and referenced handles or requests. Returns non-zero if "stop" in UV::Loop was called and there are still active handles or requests. Returns zero in all other cases.

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

  • UV_RUN_ONCE Poll for i/o once. Note that this function blocks if there are no pending callbacks. Returns zero when done (no active handles or requests left), or non-zero if more callbacks are expected (meaning you should run the event loop again sometime in the future).



The stop method stops the event loop, causing "run" in UV::Loop 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.



The update_time method updates the event loop's concept of "now" in UV::Loop. Libuv caches the current time at the start of the event loop tick in order to reduce the number of time-related system calls.

You won't normally need to call this method unless you have callbacks that block the event loop for longer periods of time, where "longer" is somewhat subjective but probably on the order of a millisecond or more.


    # although you can do it, calling ->walk() without a callback is pretty
    # useless.
    # call with no callback
    $loop->walk(sub {});

    # instead, let's walk the loop and cleanup any handles attached and then
    # completely close the loop.
    $loop->walk(sub {
        my $handle = shift;
        # check to make sure the handle can stop
        $handle->stop() if $handle->can('stop');
        $handle->close() unless $handle->closing();

The walk method will walk the list of handles and fire off the callback supplied.

This is an excellent way to ensure your loop is completely cleaned up.


Chase Whitener <>


Daisuke Murase <>


Copyright 2012, Daisuke Murase.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.