1*1c60b9acSAndroid Build Coastguard Worker# Considerations around Event Loops 2*1c60b9acSAndroid Build Coastguard Worker 3*1c60b9acSAndroid Build Coastguard WorkerMuch of the software we use is written around an **event loop**. Some examples 4*1c60b9acSAndroid Build Coastguard Worker 5*1c60b9acSAndroid Build Coastguard Worker - Chrome / Chromium, transmission, tmux, ntp SNTP... [libevent](https://libevent.org/) 6*1c60b9acSAndroid Build Coastguard Worker - node.js / cjdns / Julia / cmake ... [libuv](https://archive.is/64pOt) 7*1c60b9acSAndroid Build Coastguard Worker - Gstreamer, Gnome / GTK apps ... [glib](https://people.gnome.org/~desrt/glib-docs/glib-The-Main-Event-Loop.html) 8*1c60b9acSAndroid Build Coastguard Worker - SystemD ... sdevent 9*1c60b9acSAndroid Build Coastguard Worker - OpenWRT ... uloop 10*1c60b9acSAndroid Build Coastguard Worker 11*1c60b9acSAndroid Build Coastguard WorkerMany applications roll their own event loop using poll() or epoll() or similar, 12*1c60b9acSAndroid Build Coastguard Workerusing the same techniques. Another set of apps use message dispatchers that 13*1c60b9acSAndroid Build Coastguard Workertake the same approach, but are for cases that don't need to support sockets. 14*1c60b9acSAndroid Build Coastguard WorkerEvent libraries provide crossplatform abstractions for this functoinality, and 15*1c60b9acSAndroid Build Coastguard Workerprovide the best backend for their event waits on the platform automagically. 16*1c60b9acSAndroid Build Coastguard Worker 17*1c60b9acSAndroid Build Coastguard Workerlibwebsockets networking operations require an event loop, it provides a default 18*1c60b9acSAndroid Build Coastguard Workerone for the platform (based on poll() for Unix) if needed, but also can natively 19*1c60b9acSAndroid Build Coastguard Workeruse any of the event loop libraries listed above, including "foreign" loops 20*1c60b9acSAndroid Build Coastguard Workeralready created and managed by the application. 21*1c60b9acSAndroid Build Coastguard Worker 22*1c60b9acSAndroid Build Coastguard Worker## What is an 'event loop'? 23*1c60b9acSAndroid Build Coastguard Worker 24*1c60b9acSAndroid Build Coastguard WorkerEvent loops have the following characteristics: 25*1c60b9acSAndroid Build Coastguard Worker 26*1c60b9acSAndroid Build Coastguard Worker - they have a **single thread**, therefore they do not require locking 27*1c60b9acSAndroid Build Coastguard Worker - they are **not threadsafe** 28*1c60b9acSAndroid Build Coastguard Worker - they require **nonblocking IO** 29*1c60b9acSAndroid Build Coastguard Worker - they **sleep** while there are no events (aka the "event wait") 30*1c60b9acSAndroid Build Coastguard Worker - if one or more event seen, they call back into user code to handle each in 31*1c60b9acSAndroid Build Coastguard Worker turn and then return to the wait (ie, "loop") 32*1c60b9acSAndroid Build Coastguard Worker 33*1c60b9acSAndroid Build Coastguard Worker### They have a single thread 34*1c60b9acSAndroid Build Coastguard Worker 35*1c60b9acSAndroid Build Coastguard WorkerBy doing everything in turn on a single thread, there can be no possibility of 36*1c60b9acSAndroid Build Coastguard Workerconflicting access to resources from different threads... if the single thread 37*1c60b9acSAndroid Build Coastguard Workeris in callback A, it cannot be in two places at the same time and also in 38*1c60b9acSAndroid Build Coastguard Workercallback B accessing the same thing: it can never run any other code 39*1c60b9acSAndroid Build Coastguard Workerconcurrently, only sequentially, by design. 40*1c60b9acSAndroid Build Coastguard Worker 41*1c60b9acSAndroid Build Coastguard WorkerIt means that all mutexes and other synchronization and locking can be 42*1c60b9acSAndroid Build Coastguard Workereliminated, along with the many kinds of bugs related to them. 43*1c60b9acSAndroid Build Coastguard Worker 44*1c60b9acSAndroid Build Coastguard Worker### They are not threadsafe 45*1c60b9acSAndroid Build Coastguard Worker 46*1c60b9acSAndroid Build Coastguard WorkerEvent loops mandate doing everything in a single thread. You cannot call their 47*1c60b9acSAndroid Build Coastguard Workerapis from other threads, since there is no protection against reentrancy. 48*1c60b9acSAndroid Build Coastguard Worker 49*1c60b9acSAndroid Build Coastguard WorkerLws apis cannot be called safely from any thread other than the event loop one, 50*1c60b9acSAndroid Build Coastguard Workerwith the sole exception of `lws_cancel_service()`. 51*1c60b9acSAndroid Build Coastguard Worker 52*1c60b9acSAndroid Build Coastguard Worker### They have nonblocking IO 53*1c60b9acSAndroid Build Coastguard Worker 54*1c60b9acSAndroid Build Coastguard WorkerWith blocking IO, you have to create threads in order to block them to learn 55*1c60b9acSAndroid Build Coastguard Workerwhen your IO could proceed. In an event loop, all descriptors are set to use 56*1c60b9acSAndroid Build Coastguard Workernonblocking mode, we only attempt to read or write when we have been informed by 57*1c60b9acSAndroid Build Coastguard Workeran event that there is something to read, or it is possible to write. 58*1c60b9acSAndroid Build Coastguard Worker 59*1c60b9acSAndroid Build Coastguard WorkerSo sacrificial, blocking discrete IO threads are also eliminated, we just do 60*1c60b9acSAndroid Build Coastguard Workerwhat we should do sequentially, when we get the event indicating that we should 61*1c60b9acSAndroid Build Coastguard Workerdo it. 62*1c60b9acSAndroid Build Coastguard Worker 63*1c60b9acSAndroid Build Coastguard Worker### They sleep while there are no events 64*1c60b9acSAndroid Build Coastguard Worker 65*1c60b9acSAndroid Build Coastguard WorkerAn OS "wait" of some kind is used to sleep the event loop thread until something 66*1c60b9acSAndroid Build Coastguard Workerto do. There's an explicit wait on file descriptors that have pending read or 67*1c60b9acSAndroid Build Coastguard Workerwrite, and also an implicit wait for the next scheduled event. Even if idle for 68*1c60b9acSAndroid Build Coastguard Workerdescriptor events, the event loop will wake and handle scheduled events at the 69*1c60b9acSAndroid Build Coastguard Workerright time. 70*1c60b9acSAndroid Build Coastguard Worker 71*1c60b9acSAndroid Build Coastguard WorkerIn an idle system, the event loop stays in the wait and takes 0% CPU. 72*1c60b9acSAndroid Build Coastguard Worker 73*1c60b9acSAndroid Build Coastguard Worker### If one or more event, they handle them and then return to sleep 74*1c60b9acSAndroid Build Coastguard Worker 75*1c60b9acSAndroid Build Coastguard WorkerAs you can expect from "event loop", it is an infinite loop alternating between 76*1c60b9acSAndroid Build Coastguard Workersleeping in the event wait and sequentially servicing pending events, by calling 77*1c60b9acSAndroid Build Coastguard Workercallbacks for each event on each object. 78*1c60b9acSAndroid Build Coastguard Worker 79*1c60b9acSAndroid Build Coastguard WorkerThe callbacks handle the event and then "return to the event loop". The state 80*1c60b9acSAndroid Build Coastguard Workerof things in the loop itself is guaranteed to stay consistent while in a user 81*1c60b9acSAndroid Build Coastguard Workercallback, until you return from the callback to the event loop, when socket 82*1c60b9acSAndroid Build Coastguard Workercloses may be processed and lead to object destruction. 83*1c60b9acSAndroid Build Coastguard Worker 84*1c60b9acSAndroid Build Coastguard WorkerEvent libraries like libevent are operating the same way, once you start the 85*1c60b9acSAndroid Build Coastguard Workerevent loop, it sits in an inifinite loop in the library, calling back on events 86*1c60b9acSAndroid Build Coastguard Workeruntil you "stop" or "break" the loop by calling apis. 87*1c60b9acSAndroid Build Coastguard Worker 88*1c60b9acSAndroid Build Coastguard Worker## Why are event libraries popular? 89*1c60b9acSAndroid Build Coastguard Worker 90*1c60b9acSAndroid Build Coastguard WorkerDevelopers prefer an external library solution for the event loop because: 91*1c60b9acSAndroid Build Coastguard Worker 92*1c60b9acSAndroid Build Coastguard Worker - the quality is generally higher than self-rolled ones. Someone else is 93*1c60b9acSAndroid Build Coastguard Worker maintaining it, a fulltime team in some cases. 94*1c60b9acSAndroid Build Coastguard Worker - the event libraries are crossplatform, they will pick the most effective 95*1c60b9acSAndroid Build Coastguard Worker event wait for the platform without the developer having to know the details. 96*1c60b9acSAndroid Build Coastguard Worker For example most libs can conceal whether the platform is windows or unix, 97*1c60b9acSAndroid Build Coastguard Worker and use native waits like epoll() or WSA accordingly. 98*1c60b9acSAndroid Build Coastguard Worker - If your application uses a event library, it is possible to integrate very 99*1c60b9acSAndroid Build Coastguard Worker cleanly with other libraries like lws that can use the same event library. 100*1c60b9acSAndroid Build Coastguard Worker That is extremely messy or downright impossible to do with hand-rolled loops. 101*1c60b9acSAndroid Build Coastguard Worker 102*1c60b9acSAndroid Build Coastguard WorkerCompared to just throwing threads on it 103*1c60b9acSAndroid Build Coastguard Worker 104*1c60b9acSAndroid Build Coastguard Worker - thread lifecycle has to be closely managed, threads must start and must be 105*1c60b9acSAndroid Build Coastguard Worker brought to an end in a controlled way. Event loops may end and destroy 106*1c60b9acSAndroid Build Coastguard Worker objects they control at any time a callback returns to the event loop. 107*1c60b9acSAndroid Build Coastguard Worker 108*1c60b9acSAndroid Build Coastguard Worker - threads may do things sequentially or genuinely concurrently, this requires 109*1c60b9acSAndroid Build Coastguard Worker locking and careful management so only deterministic and expected things 110*1c60b9acSAndroid Build Coastguard Worker happen at the user data. 111*1c60b9acSAndroid Build Coastguard Worker 112*1c60b9acSAndroid Build Coastguard Worker - threads do not scale well to, eg, serving tens of thousands of connections; 113*1c60b9acSAndroid Build Coastguard Worker web servers use event loops. 114*1c60b9acSAndroid Build Coastguard Worker 115*1c60b9acSAndroid Build Coastguard Worker## Multiple codebases cooperating on one event loop 116*1c60b9acSAndroid Build Coastguard Worker 117*1c60b9acSAndroid Build Coastguard WorkerThe ideal situation is all your code operates via a single event loop thread. 118*1c60b9acSAndroid Build Coastguard WorkerFor lws-only code, including lws_protocols callbacks, this is the normal state 119*1c60b9acSAndroid Build Coastguard Workerof affairs. 120*1c60b9acSAndroid Build Coastguard Worker 121*1c60b9acSAndroid Build Coastguard WorkerWhen there is other code that also needs to handle events, say already existing 122*1c60b9acSAndroid Build Coastguard Workerapplication code, or code handling a protocol not supported by lws, there are a 123*1c60b9acSAndroid Build Coastguard Workerfew options to allow them to work together, which is "best" depends on the 124*1c60b9acSAndroid Build Coastguard Workerdetails of what you're trying to do and what the existing code looks like. 125*1c60b9acSAndroid Build Coastguard WorkerIn descending order of desirability: 126*1c60b9acSAndroid Build Coastguard Worker 127*1c60b9acSAndroid Build Coastguard Worker### 1) Use a common event library for both lws and application code 128*1c60b9acSAndroid Build Coastguard Worker 129*1c60b9acSAndroid Build Coastguard WorkerThis is the best choice for Linux-class devices. If you write your application 130*1c60b9acSAndroid Build Coastguard Workerto use, eg, a libevent loop, then you only need to configure lws to also use 131*1c60b9acSAndroid Build Coastguard Workeryour libevent loop for them to be able to interoperate perfectly. Lws will 132*1c60b9acSAndroid Build Coastguard Workeroperate as a guest on this "foreign loop", and can cleanly create and destroy 133*1c60b9acSAndroid Build Coastguard Workerits context on the loop without disturbing the loop. 134*1c60b9acSAndroid Build Coastguard Worker 135*1c60b9acSAndroid Build Coastguard WorkerIn addition, your application can merge and interoperate with any other 136*1c60b9acSAndroid Build Coastguard Workerlibevent-capable libraries the same way, and compared to hand-rolled loops, the 137*1c60b9acSAndroid Build Coastguard Workerquality will be higher. 138*1c60b9acSAndroid Build Coastguard Worker 139*1c60b9acSAndroid Build Coastguard Worker### 2) Use lws native wsi semantics in the other code too 140*1c60b9acSAndroid Build Coastguard Worker 141*1c60b9acSAndroid Build Coastguard WorkerLws supports raw sockets and file fd abstractions inside the event loop. So if 142*1c60b9acSAndroid Build Coastguard Workeryour other code fits into that model, one way is to express your connections as 143*1c60b9acSAndroid Build Coastguard Worker"RAW" wsis and handle them using lws_protocols callback semantics. 144*1c60b9acSAndroid Build Coastguard Worker 145*1c60b9acSAndroid Build Coastguard WorkerThis ties the application code to lws, but it has the advantage that the 146*1c60b9acSAndroid Build Coastguard Workerresulting code is aware of the underlying event loop implementation and will 147*1c60b9acSAndroid Build Coastguard Workerwork no matter what it is. 148*1c60b9acSAndroid Build Coastguard Worker 149*1c60b9acSAndroid Build Coastguard Worker### 3) Make a custom lws event lib shim for your custom loop 150*1c60b9acSAndroid Build Coastguard Worker 151*1c60b9acSAndroid Build Coastguard WorkerLws provides an ops struct abstraction in order to integrate with event 152*1c60b9acSAndroid Build Coastguard Workerlibraries, you can find it in ./includes/libwebsockets/lws-eventlib-exports.h. 153*1c60b9acSAndroid Build Coastguard Worker 154*1c60b9acSAndroid Build Coastguard WorkerLws uses this interface to implement its own event library plugins, but you can 155*1c60b9acSAndroid Build Coastguard Workeralso use it to make your own customized event loop shim, in the case there is 156*1c60b9acSAndroid Build Coastguard Workertoo much written for your custom event loop to be practical to change it. 157*1c60b9acSAndroid Build Coastguard Worker 158*1c60b9acSAndroid Build Coastguard WorkerIn other words this is a way to write a customized event lib "plugin" and tell 159*1c60b9acSAndroid Build Coastguard Workerthe lws_context to use it at creation time. See [minimal-http-server.c](https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/http-server/minimal-http-server-eventlib-custom/minimal-http-server.c) 160*1c60b9acSAndroid Build Coastguard Worker 161*1c60b9acSAndroid Build Coastguard Worker### 4) Cooperate at thread level 162*1c60b9acSAndroid Build Coastguard Worker 163*1c60b9acSAndroid Build Coastguard WorkerThis is less desirable because it gives up on unifying the code to run from a 164*1c60b9acSAndroid Build Coastguard Workersingle thread, it means the codebases cannot call each other's apis directly. 165*1c60b9acSAndroid Build Coastguard Worker 166*1c60b9acSAndroid Build Coastguard WorkerIn this scheme the existing threads do their own thing, lock a shared 167*1c60b9acSAndroid Build Coastguard Workerarea of memory and list what they want done from the lws thread context, before 168*1c60b9acSAndroid Build Coastguard Workercalling `lws_cancel_service()` to break the lws event wait. Lws will then 169*1c60b9acSAndroid Build Coastguard Workerbroadcast a `LWS_CALLBACK_EVENT_WAIT_CANCELLED` protocol callback, the handler 170*1c60b9acSAndroid Build Coastguard Workerfor which can lock the shared area and perform the requested operations from the 171*1c60b9acSAndroid Build Coastguard Workerlws thread context. 172*1c60b9acSAndroid Build Coastguard Worker 173*1c60b9acSAndroid Build Coastguard Worker### 5) Glue the loops together to wait sequentially (don't do this) 174*1c60b9acSAndroid Build Coastguard Worker 175*1c60b9acSAndroid Build Coastguard WorkerIf you have two or more chunks of code with their own waits, it may be tempting 176*1c60b9acSAndroid Build Coastguard Workerto have them wait sequentially in an outer event loop. (This is only possible 177*1c60b9acSAndroid Build Coastguard Workerwith the lws default loop and not the event library support, event libraries 178*1c60b9acSAndroid Build Coastguard Workerhave this loop inside their own `...run(loop)` apis.) 179*1c60b9acSAndroid Build Coastguard Worker 180*1c60b9acSAndroid Build Coastguard Worker``` 181*1c60b9acSAndroid Build Coastguard Worker while (1) { 182*1c60b9acSAndroid Build Coastguard Worker do_lws_wait(); /* interrupted at short intervals */ 183*1c60b9acSAndroid Build Coastguard Worker do_app_wait(); /* interrupted at short intervals */ 184*1c60b9acSAndroid Build Coastguard Worker } 185*1c60b9acSAndroid Build Coastguard Worker``` 186*1c60b9acSAndroid Build Coastguard Worker 187*1c60b9acSAndroid Build Coastguard WorkerThis never works well, either: 188*1c60b9acSAndroid Build Coastguard Worker 189*1c60b9acSAndroid Build Coastguard Worker - the whole thing spins at 100% CPU when idle, or 190*1c60b9acSAndroid Build Coastguard Worker 191*1c60b9acSAndroid Build Coastguard Worker - the waits have timeouts where they sleep for short periods, but then the 192*1c60b9acSAndroid Build Coastguard Worker latency to service on set of events is increased by the idle timeout period 193*1c60b9acSAndroid Build Coastguard Worker of the wait for other set of events 194*1c60b9acSAndroid Build Coastguard Worker 195*1c60b9acSAndroid Build Coastguard Worker## Common Misunderstandings 196*1c60b9acSAndroid Build Coastguard Worker 197*1c60b9acSAndroid Build Coastguard Worker### "Real Men Use Threads" 198*1c60b9acSAndroid Build Coastguard Worker 199*1c60b9acSAndroid Build Coastguard WorkerSometimes you need threads or child processes. But typically, whatever you're 200*1c60b9acSAndroid Build Coastguard Workertrying to do does not literally require threads. Threads are an architectural 201*1c60b9acSAndroid Build Coastguard Workerchoice that can go either way depending on the goal and the constraints. 202*1c60b9acSAndroid Build Coastguard Worker 203*1c60b9acSAndroid Build Coastguard WorkerAny thread you add should have a clear reason to specifically be a thread and 204*1c60b9acSAndroid Build Coastguard Workernot done on the event loop, without a new thread or the consequent locking (and 205*1c60b9acSAndroid Build Coastguard Workerbugs). 206*1c60b9acSAndroid Build Coastguard Worker 207*1c60b9acSAndroid Build Coastguard Worker### But blocking IO is faster and simpler 208*1c60b9acSAndroid Build Coastguard Worker 209*1c60b9acSAndroid Build Coastguard WorkerNo, blocking IO has a lot of costs to conceal the event wait by blocking. 210*1c60b9acSAndroid Build Coastguard Worker 211*1c60b9acSAndroid Build Coastguard WorkerFor any IO that may wait, you must spawn an IO thread for it, purely to handle 212*1c60b9acSAndroid Build Coastguard Workerthe situation you get blocked in read() or write() for an arbitrary amount of 213*1c60b9acSAndroid Build Coastguard Workertime. It buys you a simple story in one place, that you will proceed on the 214*1c60b9acSAndroid Build Coastguard Workerthread if read() or write() has completed, but costs threads and locking to get 215*1c60b9acSAndroid Build Coastguard Workerto that. 216*1c60b9acSAndroid Build Coastguard Worker 217*1c60b9acSAndroid Build Coastguard WorkerEvent loops dispense with the threads and locking, and still provide a simple 218*1c60b9acSAndroid Build Coastguard Workerstory, you will get called back when data arrives or you may send. 219*1c60b9acSAndroid Build Coastguard Worker 220*1c60b9acSAndroid Build Coastguard WorkerEvent loops can scale much better, a busy server with 50,000 connections active 221*1c60b9acSAndroid Build Coastguard Workerdoes not have to pay the overhead of 50,000 threads and their competing for 222*1c60b9acSAndroid Build Coastguard Workerlocking. 223*1c60b9acSAndroid Build Coastguard Worker 224*1c60b9acSAndroid Build Coastguard WorkerWith blocked threads, the thread can do no useful work at all while it is stuck 225*1c60b9acSAndroid Build Coastguard Workerwaiting. With event loops the thread can service other events until something 226*1c60b9acSAndroid Build Coastguard Workerhappens on the fd. 227*1c60b9acSAndroid Build Coastguard Worker 228*1c60b9acSAndroid Build Coastguard Worker### Threads are inexpensive 229*1c60b9acSAndroid Build Coastguard Worker 230*1c60b9acSAndroid Build Coastguard WorkerIn the cases you really need threads, you must have them, or fork off another 231*1c60b9acSAndroid Build Coastguard Workerprocess. But if you don't really need them, they bring with them a lot of 232*1c60b9acSAndroid Build Coastguard Workerexpense, some you may only notice when your code runs on constrained targets 233*1c60b9acSAndroid Build Coastguard Worker 234*1c60b9acSAndroid Build Coastguard Worker - threads have an OS-side footprint both as objects and in the scheduler 235*1c60b9acSAndroid Build Coastguard Worker 236*1c60b9acSAndroid Build Coastguard Worker - thread context switches are not slow on modern CPUs, but have side effects 237*1c60b9acSAndroid Build Coastguard Worker like cache flushing 238*1c60b9acSAndroid Build Coastguard Worker 239*1c60b9acSAndroid Build Coastguard Worker - threads are designed to be blocked for arbitrary amounts of time if you use 240*1c60b9acSAndroid Build Coastguard Worker blocking IO apis like write() or read(). Then how much concurrency is really 241*1c60b9acSAndroid Build Coastguard Worker happening? Since blocked threads just go away silently, it is hard to know 242*1c60b9acSAndroid Build Coastguard Worker when in fact your thread is almost always blocked and not doing useful work. 243*1c60b9acSAndroid Build Coastguard Worker 244*1c60b9acSAndroid Build Coastguard Worker - threads require their own stack, which is on embedded is typically suffering 245*1c60b9acSAndroid Build Coastguard Worker from a dedicated worst-case allocation where the headroom is usually idle 246*1c60b9acSAndroid Build Coastguard Worker 247*1c60b9acSAndroid Build Coastguard Worker - locking must be handled, and missed locking or lock order bugs found 248*1c60b9acSAndroid Build Coastguard Worker 249*1c60b9acSAndroid Build Coastguard Worker### But... what about latency if only one thing happens at a time? 250*1c60b9acSAndroid Build Coastguard Worker 251*1c60b9acSAndroid Build Coastguard Worker - Typically, at CPU speeds, nothing is happening at any given time on most 252*1c60b9acSAndroid Build Coastguard Worker systems, the event loop is spending most of its time in the event wait 253*1c60b9acSAndroid Build Coastguard Worker asleep at 0% cpu. 254*1c60b9acSAndroid Build Coastguard Worker 255*1c60b9acSAndroid Build Coastguard Worker - The POSIX sockets layer is disjoint from the actual network device driver. 256*1c60b9acSAndroid Build Coastguard Worker It means that once you hand off the packet to the networking stack, the POSIX 257*1c60b9acSAndroid Build Coastguard Worker api just returns and leaves the rest of the scheduling, retries etc to the 258*1c60b9acSAndroid Build Coastguard Worker networking stack and device, descriptor queuing is driven by interrupts in 259*1c60b9acSAndroid Build Coastguard Worker the driver part completely unaffected by the event loop part. 260*1c60b9acSAndroid Build Coastguard Worker 261*1c60b9acSAndroid Build Coastguard Worker - Passing data around via POSIX apis between the user code and the networking 262*1c60b9acSAndroid Build Coastguard Worker stack tends to return almost immediately since its onward path is managed 263*1c60b9acSAndroid Build Coastguard Worker later in another, usually interrupt, context. 264*1c60b9acSAndroid Build Coastguard Worker 265*1c60b9acSAndroid Build Coastguard Worker - So long as enough packets-worth of data are in the network stack ready to be 266*1c60b9acSAndroid Build Coastguard Worker handed to descriptors, actual throughput is completely insensitive to jitter 267*1c60b9acSAndroid Build Coastguard Worker or latency at the application event loop 268*1c60b9acSAndroid Build Coastguard Worker 269*1c60b9acSAndroid Build Coastguard Worker - The network device itself is inherently serializing packets, it can only send 270*1c60b9acSAndroid Build Coastguard Worker one thing at a time. The networking stack locking also introduces hidden 271*1c60b9acSAndroid Build Coastguard Worker serialization by blocking multiple threads. 272*1c60b9acSAndroid Build Coastguard Worker 273*1c60b9acSAndroid Build Coastguard Worker - Many user systems are decoupled like the network stack and POSIX... the user 274*1c60b9acSAndroid Build Coastguard Worker event loop and its latencies do not affect backend processes occurring in 275*1c60b9acSAndroid Build Coastguard Worker interrupt or internal thread or other process contexts 276*1c60b9acSAndroid Build Coastguard Worker 277*1c60b9acSAndroid Build Coastguard Worker## Conclusion 278*1c60b9acSAndroid Build Coastguard Worker 279*1c60b9acSAndroid Build Coastguard WorkerEvent loops have been around for a very long time and are in wide use today due 280*1c60b9acSAndroid Build Coastguard Workerto their advantages. Working with them successfully requires understand how to 281*1c60b9acSAndroid Build Coastguard Workeruse them and why they have the advantages and restrictions they do. 282*1c60b9acSAndroid Build Coastguard Worker 283*1c60b9acSAndroid Build Coastguard WorkerThe best results come from all the participants joining the same loop directly. 284*1c60b9acSAndroid Build Coastguard WorkerUsing a common event library in the participating codebases allows completely 285*1c60b9acSAndroid Build Coastguard Workerdifferent code can call each other's apis safely without locking. 286