[Libwebsockets] Example of custom event loop integration?

Andy Green andy at warmcat.com
Sun May 30 07:35:53 CEST 2021

On 5/30/21 1:21 AM, Felipe Gasper wrote:

Hi Felipe -

> 	I’m considering writing a Perl binding to libwebsockets. For this to work I need to be able to integrate libwebsockets into whatever event loop the Perl application runs. (There are many loops, and three widely-used abstraction interfaces over them.)
> 	I found the HTTP-server foreign event lib integration example: https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c
> 	This example, though, appears only to use event libraries that libwebsockets natively supports. Does libwebsockets include an interface like libcurl’s multi_socket interface (cf. https://curl.se/libcurl/c/libcurl-multi.html)? That seems to be what `struct lws_event_loop_ops` and `struct lws_plugin_evlib` represent … are there any examples of giving these structs to libwebsockets at runtime?

On the one hand, passing a struct lws_event_loop_ops * in at context 
creation time is easy to add.  But I am not sure I understand the 
problem you are describing well enough...

Typically a library or process / subprocess "pick an event loop", if I 
understand it part of the system deciding to use an abstraction layer 
(or three :-) ) between it and the actual loop, doesn't change that 
there's a specific loop library running the show underneath, nor affect 
compatibility then with joining the real loop below the abstraction if 
you support it natively.  So native support for a range of event libs 
remains the best choice AFAIK.

As you saw with the foreign example, lws already lets you pick the loop 
at runtime, not just buildtime, and already builds the plugins 
separately from the library, meaning all necessary apis are already 
public and available for integration if the app wants to produce a 
custom lws_event_loop_ops.  (It's like that so linux distros can package 
one build of lws that will work correctly with code, packaged or not, 
that use any of the loops.  Packaged code can express a dependency on 
lws and the sub-package containing the loop plugin that it needs.)

There are indeed many loop libraries out there but it's a finite number 
and we already support the major ones, and some minor ones that were 
contributed.  We support joining and leaving a foreign loop cleanly 
without disrupting it or leaking... in particular we support that with 
libuv, which is much harder than the others because handle destruction 
is async, via the event loop, it means all kinds of close and destroy 
internally in lws had to be made async / via refcounts to work with it 
only letting us actually destroy things later.

For custom loops in the application, there is a gnarly hack from a 
decade ago it sounds like you found, the EXTERNAL_POLL support, I really 
don't recommend using this.  Modern lws offers hi res scheduling 
services (for, eg, UDP retry) that are used internally and encouraged 
for user code, since it radically improves portability, that are coming 
from modulating the wait via event lib timers or timeout computation. 
EXTERNAL_POLL's concept was much dumber, just bringing a zero-wait 
service call inside an existing custom event loop, it cannot make a 
satisfying result for both latency and cpu load.  It also has a 
dependency on protocols[0] which is user code business, and not 
available for the kind of generic integration you are looking at.


More information about the Libwebsockets mailing list