[Libwebsockets] libwebsockets and threads

Andy Green andy at warmcat.com
Tue Nov 22 22:49:07 CET 2016

On November 23, 2016 1:42:02 AM GMT+08:00, Alan Conway <aconway at redhat.com> wrote:
>From the coding README:
>> @section evtloop Libwebsockets is singlethreaded
>> Libwebsockets works in a serialized event loop, in a single thread.
>> If you insist on trying to use it from multiple threads, take special
>> care if you might simultaneously create more than one context from
>> different threads.
>Suppose I did insist, what do I have to serialize? 
>I certainly will serialize read/write per socket, but can I read/write
>on separate sockets concurrently? 
>Is it sufficient to serialize context creation or are there other
>global data structures in the library?

You should only have one lws context.

>I see the section and example
>> @section smp SMP / Multithreaded service
>But that is inside-out for me. I don't want to give threads to lws and
>have them tied to services, protocols or file-descriptors. I want to
>process bounded chunks of websocket work in the thread of my choosing
>and then switch efficiently to doing something else with that core. My
>thread count is based on my core count, not on the number of
>connections or protocols I am serving.

I think you took a slightly too quick look at the pthreads test code and confused what code is there to make threads at all, which in the test app just live to do service, and what is required by the library.

Since I dunno how it will play with synthetic fds or whatever else you want to bind it to, I just explain the existing lws per-thread support.

Lws multiple service threads is a logical-only way of compartmentalizing the management of chunks of fds in a way that service on them can be run concurrently, in the smp sense.  At the same time, incoming connection accepts are distributed between these compartments, facilitating meaningful concurrency.

Nothing about that either 'gives threads to lws', nor '[ties them] to services [or] protocols'; service threads are related to fds only in that the process fd space got logically split into concurrently servicable ranges, still under one context[1].  Inside lws these remain 'flat' and lws is not informed of any user thread objects.  The service api for particular per-thread chunks just gets called from 'somewhere', concurrent with and independent of the service api for other per-thread chunks[2].

LWS_MAX_SMP at cmake is just what it says, it sets array bounds internally for the max possible number of concurrently-servicable per-thread structs.  You choose at runtime, when creating the context, how many you actually want for that session.


[1] Primitives like 'call back everyone who is using this ws protocol when they are writable' conveniently still work across the union of all the per-thread structs, because they exist in a single context.

[2] "Service" in the lws sense means lws calls poll() for its fd range, and does housekeeping like timeout checks.  I haven't tested it with libuv/ev since the work got almost zero interest since I did it a couple of years ago.

>Libwebsockets mailing list
>Libwebsockets at ml.libwebsockets.org

More information about the Libwebsockets mailing list