Last active
July 27, 2024 09:30
-
-
Save trevnorris/1f3066ccb0fed9037afa to your computer and use it in GitHub Desktop.
rough notes on the linux side of the libuv event loop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
uv_run | |
- uv__update_time(): Update time with millisecond precision. | |
- uv__run_timers(): Loop through "heap" and run timers whose timeout > time. | |
- uv__run_pending(): Run all callbacks on the pending_queue. Remove each item | |
from the queue when run. | |
Note: uv__io_feed() is the only function to insert onto pending_queue. | |
Note: The following use uv__io_feed(): | |
- uv_pipe_connect(), but only in the case of an error. | |
- uv__write_req_finish(), part of stream.c | |
- uv_tcp_connect(), but only in the case of an error. | |
- uv__udp_send_msg(), for all sent messages. | |
- uv__run_idle(): Generated by loop-watcher.c. Run all callbacks on the queue | |
of idle_handles. The queue is not cleared by running the handles. If there | |
are idle_handles then the timeout for uv__io_poll is set to 0. Meaning the | |
event loop will immediately proceed. | |
Notes: This queue is used by the uv_idle_{init,start,stop} API. | |
- uv__run_prepare(): Generated by loop-watcher.c. Run all callbacks on the | |
queue of prepare_handles. The queue is not cleared by running the handles. | |
Notes: This queue is used by the uv_prepare_{init,start,stop} API. | |
- Calculate timeout time for epoll_wait(). | |
- uv__io_poll(..., timeout): Pass the timeout so if no poll events occur the | |
event loop will proceed so timers will run. | |
- Loop through `watcher_queue` (queue of all fd's that have an event that | |
need to be listened for, which is `pevents` [pending events]) and add the | |
associated event to the fd. | |
- Run epoll_wait with calculated timeout. | |
- If events occurred run attached callbacks and pass the event. | |
- Once timeout runs out return. | |
- uv__run_check(): Generated by loop-watcher.c. Run all callbacks on the queue | |
of check_handles. The queue is not cleared by running the handles. | |
Notes: This queue is only used by the uv_check_{init,start,stop} API. | |
- uv__run_closing_handles(): | |
* Note: while the handle is in the UV_CLOSING state now, it's still possible | |
for it to be active in the sense that uv__is_active() returns true. A good | |
example is when the user calls uv_shutdown(), immediately followed by | |
uv_close(). The handle is considered active at this point because the | |
completion of the shutdown req is still pending. | |
- Go through the linked list of handles marked for closing and run | |
uv__finish_close(). | |
- For UV_NAMED_PIPE, UV_TCP and UV_TTY run uv__stream_destroy() on the | |
handle. | |
- If there's connect_req (uv_connect_t) then unregister it on the event | |
loop the given stream is attached to using uv__req_unregister(), then | |
run the connect_req->cb() (uv_connect_cb) passing UV_ECANCELED. | |
- For every write request in write_queue (void*[2]) set error to | |
UV_ECANCELED. | |
- Pass stream to uv__write_callbacks(). | |
- Loop through the linked list of write requests and unregister each | |
uv_write_t with uv__req_unregister() (meaning, remove it from the | |
write queue). | |
- Update the write_queue_size with uv__write_req_size(), which does a | |
linear scan of all bufs in the write req using uv__count_bufs() and | |
free the request data. | |
(Note the comment on uv__write_req_finish() about why it currently | |
works this way) | |
- Run req->cb (uv_write_cb) passing the request and error. | |
- If there's a shutdown_req (uv_shutdown_t) then unregister the req and | |
call the uv_shutdown_cb() with UV_ECANCELED. | |
- For UV_UDP run uv__udp_finish_close() on the handle. | |
- Set status to UV_ECANCELED. | |
- Run uv__udp_run_completed() passing the handle. | |
- Unregister each uv_udp_send_t in the write_completed_queue. | |
- Call the send_cb() (uv_udp_send_cb) passing the status. | |
- If write_queue is empty stop the watcher by running uv__io_stop() | |
- (TODO: look into "events", "pevents", basically everything in | |
uv__io_stop()) | |
- Run uv__handle_unref() on all handles. | |
- If the handle is not active (!UV__HANDLE_ACTIVE) then decrement the | |
active_handles count on the loop. | |
- Remove handle from the handle_queue (void*[2] in UV_HANDLE_FIELDS) | |
- If has close_cb(), run and pass the closed handle. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment