Skip to content

Commit

Permalink
doc: the event loop
Browse files Browse the repository at this point in the history
  • Loading branch information
hargoniX committed Jan 13, 2025
1 parent 8db1a7e commit 94ac027
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
19 changes: 15 additions & 4 deletions src/runtime/uv/event_loop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,21 @@
Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Sofia Rodrigues
Author: Sofia Rodrigues, Henrik Böving
*/
#include "runtime/uv/event_loop.h"


/*
This file builds a thread safe event loop on top of the thread unsafe libuv event loop.
We achieve this by always having a `uv_async_t` associated with the libuv event loop.
As `uv_async_t` are a thread safe primitive it is safe to send a notification to it from another
thread. Once this notification arrives the event loop suspends its own execution and unlocks a mutex
that protects it. This mutex can then be taken by another thread that wants to work with the event
loop. After that work is done it signals a condition variable that the event loop is waiting on
to continue its execution.
*/

namespace lean {
#ifndef LEAN_EMSCRIPTEN
using namespace std;
Expand All @@ -26,8 +37,8 @@ void async_callback(uv_async_t * handle) {
uv_stop(handle->loop);
}

// Awakes the event loop and stops it so it can receive future requests.
void event_loop_wake(event_loop_t * event_loop) {
// Interrupts the event loop and stops it so it can receive future requests.
void event_loop_interrupt(event_loop_t * event_loop) {
int result = uv_async_send(&event_loop->async);
(void)result;
lean_assert(result == 0);
Expand All @@ -46,7 +57,7 @@ void event_loop_init(event_loop_t * event_loop) {
void event_loop_lock(event_loop_t * event_loop) {
if (uv_mutex_trylock(&event_loop->mutex) != 0) {
event_loop->n_waiters++;
event_loop_wake(event_loop);
event_loop_interrupt(event_loop);
uv_mutex_lock(&event_loop->mutex);
event_loop->n_waiters--;
}
Expand Down
9 changes: 4 additions & 5 deletions src/runtime/uv/event_loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ using namespace std;
// Event loop structure for managing asynchronous events and synchronization across multiple threads.
typedef struct {
uv_loop_t * loop; // The libuv event loop.
uv_mutex_t mutex; // Mutex for protecting shared resources.
uv_cond_t cond_var; // Condition variable for thread synchronization.
uv_async_t async; // Async handle to notify the main event loop.
_Atomic(int) n_waiters; // Atomic counter for managing waiters.
uv_mutex_t mutex; // Mutex for protecting `loop`.
uv_cond_t cond_var; // Condition variable for signaling that `loop` is free.
uv_async_t async; // Async handle to interrupt `loop`.
_Atomic(int) n_waiters; // Atomic counter for managing waiters for `loop`.
} event_loop_t;

// The multithreaded event loop object for all tasks in the task manager.
Expand All @@ -35,7 +35,6 @@ void event_loop_init(event_loop_t *event_loop);
void event_loop_cleanup(event_loop_t *event_loop);
void event_loop_lock(event_loop_t *event_loop);
void event_loop_unlock(event_loop_t *event_loop);
void event_loop_wake(event_loop_t *event_loop);
void event_loop_run_loop(event_loop_t *event_loop);

#endif
Expand Down

0 comments on commit 94ac027

Please sign in to comment.