andy at warmcat.com
Mon Mar 11 14:46:17 CET 2019
On March 11, 2019 9:03:28 PM GMT+08:00, Alexander Zvyagin <zvyagin.alexander at gmail.com> wrote:
>I would like to start to use threads in my code to avoid blocking in
>my server code. What is the recommended way to achieve that?!
Sometimes you do need threads. For example...
>My code is written in C++ and I would like to stay as close to the
>standard practice of writing such code as possible. On the other hand
>libwebsockets already has its own threadpool implemntation. And there
...the threadpool stuff was written for gitohashi 'blame' processing... if the result isn't already cached, to produce the result html requires a lot of cpu time, potentially tens of seconds. The api that does it in libgit2 isn't stateful, so you can't split it up into many smaller calls interleaved with returning to the event loop. If we tried to do that processing in the callback as usual, it would block the whole server for the duration. The threadpool decouples the http service action from the event loop cleanly for cases like this where the issue is big lumps of cpu load to produce a result synchronously.
It also hides thread syncing and restricts the maximum amount of resource that can be used concurrently and provides a transparent queue if that is exceeded. So if that's similar to your problem, lws threadpool should be a good fit.
>are "minimal-ws-server-threadpool" and "minimal-ws-server-threads"
>examples. Which path should I take?
...other times threads are just a way to avoid dealing with nonblocking IO or can be deconstructed into just being a different way to run some code on some event; it can be possible to just refactor out the threads to directly wait on events in the lws event loop (eg thread to handle keyboard events -> lws raw file open on /dev/input/... and receiving READ events enirely in the event loop thread). In some cases the whole "application logic" that was assumed to need a thread turns out to be perfectly doable as a synchronous state machine moving between states based on eg some button events and otherwise just network events reported by lws.
Other times you face some foreign code insisting to have its own threads and no way to adapt its architecture. In those cases you have the lws event loop doing its thing and then other threads that want to communicate with it, the -threads type examples show how to deal with it. Although the details (if ringbuffers are needed etc) depend on exactly what the thread wants to do.
>Also, do I understand correctly, that my threads should call
>lws_cancel_service() (with a mutex lock, of course) to communicate
>with the main libwebsocket loop?
This is the recommended way, because it works with poll() and all the event libraries. The underlying method is a byte written to a pipe that's emptied every time it had anything in it, so it's really cheap to do, and has good behaviour under load... if many threads or one other thread had many things needing attention and calling lws_cancel_service(), it all boils down to one cancel callback coming as soon as possible in the lws service thread context. In there it can look at linked-lists of things that wanted attention etc in one hit. Because cancel_service itself just writes into a pipe, it's threadsafe (if you take care about context destroy ordering to be after the other thread joins at shutdown). But you'd need a mutex to protect who owns your related data like linked-lists of guys that needed attention.
>Thanks a lot in advance,
>Libwebsockets mailing list
>Libwebsockets at ml.libwebsockets.org
More information about the Libwebsockets