--- libev/ev.html 2007/11/23 16:17:12 1.35 +++ libev/ev.html 2007/11/24 06:23:27 1.36 @@ -6,7 +6,7 @@ - + @@ -34,6 +34,7 @@
  • ev_child - wait for pid status changes
  • ev_idle - when you've got nothing better to do
  • ev_prepare and ev_check - customise your event loop
  • +
  • ev_embed - when one backend isn't enough
  • OTHER FUNCTIONS
  • @@ -159,6 +160,15 @@ (assuming you know what you are doing). This is the set of backends that libev will probe for if you specify no backends explicitly.

    +
    unsigned int ev_embeddable_backends ()
    +
    +

    Returns the set of backends that are embeddable in other event loops. This +is the theoretical, all-platform, value. To find which backends +might be supported on the current system, you would need to look at +ev_embeddable_backends () & ev_supported_backends (), likewise for +recommended ones.

    +

    See the description of ev_embed watchers for more info.

    +
    ev_set_allocator (void *(*cb)(void *ptr, long size))

    Sets the allocation function to use (the prototype is similar to the @@ -933,6 +943,10 @@

    + + + +

    ev_child - wait for pid status changes

    @@ -1015,9 +1029,10 @@

    Prepare and check watchers are usually (but not always) used in tandem: prepare watchers get invoked before the process blocks and check watchers afterwards.

    -

    Their main purpose is to integrate other event mechanisms into libev. This -could be used, for example, to track variable changes, implement your own -watchers, integrate net-snmp or a coroutine library and lots more.

    +

    Their main purpose is to integrate other event mechanisms into libev and +their use is somewhat advanced. This could be used, for example, to track +variable changes, implement your own watchers, integrate net-snmp or a +coroutine library and lots more.

    This is done by examining in each prepare call which file descriptors need to be watched by the other library, registering ev_io watchers for them and starting an ev_timer watcher for any timeouts (many libraries @@ -1047,6 +1062,72 @@ + + +

    +

    ev_embed - when one backend isn't enough

    +
    +

    This is a rather advanced watcher type that lets you embed one event loop +into another.

    +

    There are primarily two reasons you would want that: work around bugs and +prioritise I/O.

    +

    As an example for a bug workaround, the kqueue backend might only support +sockets on some platform, so it is unusable as generic backend, but you +still want to make use of it because you have many sockets and it scales +so nicely. In this case, you would create a kqueue-based loop and embed it +into your default loop (which might use e.g. poll). Overall operation will +be a bit slower because first libev has to poll and then call kevent, but +at least you can use both at what they are best.

    +

    As for prioritising I/O: rarely you have the case where some fds have +to be watched and handled very quickly (with low latency), and even +priorities and idle watchers might have too much overhead. In this case +you would put all the high priority stuff in one loop and all the rest in +a second one, and embed the second one in the first.

    +

    As long as the watcher is started it will automatically handle events. The +callback will be invoked whenever some events have been handled. You can +set the callback to 0 to avoid having to specify one if you are not +interested in that.

    +

    Also, there have not currently been made special provisions for forking: +when you fork, you not only have to call ev_loop_fork on both loops, +but you will also have to stop and restart any ev_embed watchers +yourself.

    +

    Unfortunately, not all backends are embeddable, only the ones returned by +ev_embeddable_backends are, which, unfortunately, does not include any +portable one.

    +

    So when you want to use this feature you will always have to be prepared +that you cannot get an embeddable loop. The recommended way to get around +this is to have a separate variables for your embeddable loop, try to +create it, and if that fails, use the normal loop for everything:

    +
      struct ev_loop *loop_hi = ev_default_init (0);
    +  struct ev_loop *loop_lo = 0;
    +  struct ev_embed embed;
    +
    +  // see if there is a chance of getting one that works
    +  // (remember that a flags value of 0 means autodetection)
    +  loop_lo = ev_embeddable_backends () & ev_recommended_backends ()
    +    ? ev_loop_new (ev_embeddable_backends () & ev_recommended_backends ())
    +    : 0;
    +
    +  // if we got one, then embed it, otherwise default to loop_hi
    +  if (loop_lo)
    +    {
    +      ev_embed_init (&embed, 0, loop_lo);
    +      ev_embed_start (loop_hi, &embed);
    +    }
    +  else
    +    loop_lo = loop_hi;
    +
    +
    +
    +
    ev_embed_init (ev_embed *, callback, struct ev_loop *loop)
    +
    ev_embed_set (ev_embed *, callback, struct ev_loop *loop)
    +
    +

    Configures the watcher to embed the given loop, which must be embeddable.

    +
    +
    + + +