<div dir="ltr"><div class="gmail_default" style="font-size:x-small">Nicolas,</div><div class="gmail_default" style="font-size:x-small"><br></div><div class="gmail_default" style="font-size:x-small">I have been using libwebsocket with an external event epoll loop for years now.</div><div class="gmail_default" style="font-size:x-small">It is quite straightforward and very stable.</div><div class="gmail_default" style="font-size:x-small"><br></div><div class="gmail_default" style="font-size:x-small">I have the libwebsocket running inside a thread from my framework. That thread has all the epolling mechanism build in.</div><div class="gmail_default" style="font-size:x-small">I use the lws xxx_POLL_FD callbacks (in the http[0] protocol) to add, modify and remove a file descriptor, like for a normal fd except that these fds are created by lws.<br></div><div class="gmail_default" style="font-size:x-small"><br></div><div class="gmail_default" style="font-size:x-small">The rest of the lws callback mechanism is working as it should, nothing special to do here.</div><div class="gmail_default" style="font-size:x-small"><br></div><div class="gmail_default" style="font-size:x-small">I hope it helps,</div><div class="gmail_default" style="font-size:x-small"><br></div><div class="gmail_default" style="font-size:x-small">Andy, I hope this won't be removed for V3.0 ? Thanks.</div><div class="gmail_default" style="font-size:x-small"><br></div><div class="gmail_default" style="font-size:x-small">Brice.</div><div class="gmail_default" style="font-size:x-small"><br></div><div class="gmail_default" style="font-size:x-small"><br></div><div class="gmail_default" style="font-size:x-small"><br></div><div class="gmail_default" style="font-size:x-small"><br></div><div class="gmail_default" style="font-size:x-small"><br></div><div class="gmail_default" style="font-size:x-small"><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Sep 24, 2018 at 12:30 PM Andy Green <<a href="mailto:andy@warmcat.com">andy@warmcat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
<br>
On 24/09/2018 23:15, Nicolas Cornu wrote:<br>
> Hello,<br>
> <br>
> I'm trying to adapt libwebsockets to a new (barely unused) event-loop. I<br>
> read this page:<br>
> <a href="https://libwebsockets.org/git/libwebsockets/tree/lib/event-libs" rel="noreferrer" target="_blank">https://libwebsockets.org/git/libwebsockets/tree/lib/event-libs</a> . I find<br>
> it difficult for two reasons.<br>
<br>
Well, at least you don't find it difficult because the event loop <br>
support - which by now supports libuv, libev, libevent and poll - is not <br>
neatly isolated into a nice "ops" callback struct.<br>
<br>
That's new for v3.0 - before that libevent support was contributed by a <br>
Samsung dude without that advantage, the event loop stuff was spread all <br>
over the code.  So since he found that possible - he just sent the patch <br>
one day out of the blue - the situation is actually a lot easier for you.<br>
<br>
> First, names of callbacks in lws_event_loop_ops are not clear<br>
> (wsi_logical_close, init_pt, destroy_context2, ...).<br>
<br>
If you look in the ops struct definition, there is a little more advice<br>
<br>
struct lws_event_loop_ops {<br>
        const char *name;<br>
        /* event loop-specific context init during context creation */<br>
        int (*init_context)(struct lws_context *context,<br>
                            const struct lws_context_creation_info *info);<br>
        /* called during lws_destroy_context */<br>
        int (*destroy_context1)(struct lws_context *context);<br>
        /* called during lws_destroy_context2 */<br>
        int (*destroy_context2)(struct lws_context *context);<br>
        /* init vhost listening wsi */<br>
        int (*init_vhost_listen_wsi)(struct lws *wsi);<br>
        /* init the event loop for a pt */<br>
        int (*init_pt)(struct lws_context *context, void *_loop, int tsi);<br>
        /* called at end of first phase of close_free_wsi()  */<br>
        int (*wsi_logical_close)(struct lws *wsi);<br>
        /* return nonzero if client connect not allowed  */<br>
        int (*check_client_connect_ok)(struct lws *wsi);<br>
        /* close handle manually  */<br>
        void (*close_handle_manually)(struct lws *wsi);<br>
        /* event loop accept processing  */<br>
        void (*accept)(struct lws *wsi);<br>
        /* control wsi active events  */<br>
        void (*io)(struct lws *wsi, int flags);<br>
        /* run the event loop for a pt */<br>
        void (*run_pt)(struct lws_context *context, int tsi);<br>
        /* called before pt is destroyed */<br>
        void (*destroy_pt)(struct lws_context *context, int tsi);<br>
        /* called just before wsi is freed  */<br>
        void (*destroy_wsi)(struct lws *wsi);<br>
<br>
        unsigned int periodic_events_available:1;<br>
};<br>
<br>
<a href="https://libwebsockets.org/git/libwebsockets/tree/lib/event-libs/private.h" rel="noreferrer" target="_blank">https://libwebsockets.org/git/libwebsockets/tree/lib/event-libs/private.h</a><br>
<br>
> Second, the callback of already existing event loops are not only here<br>
> to wrap event loop. For exemple, if we read init_context implementation<br>
> it does something else than wrapping event loop.<br>
<br>
... this stuff is a) setting up event-loop specific signal handler and <br>
b) preparing the event-loop specific watcher struct with a runtime <br>
pointer to the context, so it can operate in signal context without globals.<br>
<br>
static int<br>
elops_init_context_uv(struct lws_context *context,<br>
                      const struct lws_context_creation_info *info)<br>
{<br>
        int n;<br>
<br>
        context->eventlib_signal_cb = info->signal_cb;<br>
<br>
        for (n = 0; n < context->count_threads; n++)<br>
                context->pt[n].w_sigint.context = context;<br>
<br>
        return 0;<br>
}<br>
<br>
<br>
> So, is it possible to do better documentation about them to explain what<br>
> they should do?<br>
<br>
Sure, anything's possible.  But it's not exactly #1 on my todo list atm.<br>
<br>
If you have specific questions I will try to answer them, but the code <br>
calling the ops is all right there along with four example <br>
implementations.  You may find your event loop needs more ops, although <br>
libuv was probably the worst case for that already.<br>
<br>
Note that libuv is quite different from the other event loops because it <br>
requires asynchronous handle close later via the event loop.  So this <br>
has a lot of knock-ons to make it work properly, like having to <br>
reference-count anything with a handle so we know the moment when it's <br>
able to stop the event loop on exit; getting that wrong is catastrophic <br>
for memory leaks and clean integration with foreign loops.  Assuming <br>
your event loop is more along the lines of libevent, which doesn't have <br>
this requirement, cut-and-pasting the libevent support doesn't look that <br>
unmanageable or inexplicable:<br>
<br>
<a href="https://libwebsockets.org/git/libwebsockets/tree/lib/event-libs/libevent/libevent.c" rel="noreferrer" target="_blank">https://libwebsockets.org/git/libwebsockets/tree/lib/event-libs/libevent/libevent.c</a><br>
<br>
There are also three minimal examples that showcase various modes of <br>
using the event loop, that are easy to extend to more event loops<br>
<br>
<a href="https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/http-server/minimal-http-server-eventlib" rel="noreferrer" target="_blank">https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/http-server/minimal-http-server-eventlib</a><br>
<a href="https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/http-server/minimal-http-server-eventlib-demos" rel="noreferrer" target="_blank">https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/http-server/minimal-http-server-eventlib-demos</a><br>
<a href="https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/http-server/minimal-http-server-eventlib-foreign" rel="noreferrer" target="_blank">https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/http-server/minimal-http-server-eventlib-foreign</a><br>
<br>
The "foreign" one is interesting because it proves lws can integrate <br>
cleanly with somebody else's existing event loop without perturbing it. <br>
Although again that was more of a challenge for libuv than anything else.<br>
<br>
-Andy<br>
<br>
> Regards,<br>
> <br>
> Nicolas<br>
> <br>
> _______________________________________________<br>
> Libwebsockets mailing list<br>
> <a href="mailto:Libwebsockets@ml.libwebsockets.org" target="_blank">Libwebsockets@ml.libwebsockets.org</a><br>
> <a href="https://libwebsockets.org/mailman/listinfo/libwebsockets" rel="noreferrer" target="_blank">https://libwebsockets.org/mailman/listinfo/libwebsockets</a><br>
> <br>
_______________________________________________<br>
Libwebsockets mailing list<br>
<a href="mailto:Libwebsockets@ml.libwebsockets.org" target="_blank">Libwebsockets@ml.libwebsockets.org</a><br>
<a href="https://libwebsockets.org/mailman/listinfo/libwebsockets" rel="noreferrer" target="_blank">https://libwebsockets.org/mailman/listinfo/libwebsockets</a><br>
</blockquote></div>