iv_tls(3)

πŸ’– iv_tls β€” thread-local storage handling for ivykis modules πŸ’–

okay bestie, pull up a chair, because we're talking about iv_tls, aka the ivykis programmer's manual page for thread-local storage handling. yes, the whole iv_tls(3) situation. it's giving infrastructure, it's giving module glue, and honestly? it's iconic. let's go. ✨


🌸 SYNOPSIS 🌸

#include <iv_tls.h>

struct iv_tls_user {
        size_t          sizeof_state;
        void            (*init_thread)(void *st);
        void            (*deinit_thread)(void *st);
};

void iv_tls_user_register(struct iv_tls_user *tu);
void *iv_tls_user_ptr(const struct iv_tls_user *tu);

look at her. #include <iv_tls.h> and you're in. πŸŽ€


πŸ¦‹ DESCRIPTION πŸ¦‹

so the iv_tls interface is literally the thread-local storage plug for ivykis modules. that's it, that's the job. no cap. πŸ’…

an ivykis module can arrange for an amount of memory to be allocated for its use in each ivykis thread by calling iv_tls_user_register. and listen β€” this must be done before any calls to iv_init have been made in this process. before. like, no takebacks. it's typically done from a module initialization function marked as a constructor function, which is exactly the kind of main character entrance we respect. πŸ‘‘

the ->sizeof_state member of the passed-in structure is the vibe check on how many bytes of memory the module wants allocated for its use in every ivykis thread. every single one. 🫢

when a thread calls iv_init, ->sizeof_state bytes of memory get allocated for use by this module in that thread, and initialised to zero. (yes bestie, zeroed. free of charge.) a pointer to this memory area can be obtained by calling iv_tls_user_ptr β€” and heads up, that returns NULL in non-ivykis threads. so if you get NULL, check what kind of thread you're standing in. 😭

if the specified ->init_thread function pointer is not NULL, it will be invoked at the end of iv_init, with its argument pointing to this thread's memory area allocation for this module. cute, right? a little hook at the end. πŸŽ€

if ->deinit_thread is not NULL, it will be invoked at the start of iv_deinit β€” or, if the thread fails to call iv_deinit before terminating, at thread termination time. either way she shows up. the argument passed into ->deinit_thread is the same as for ->init_thread. symmetry, slay. ✨

it is permitted to call any ivykis API functions from the ->init_thread and ->deinit_thread callbacks. go wild (responsibly).

there is no explicit serialization on calls to ->init_thread and ->deinit_thread. that's not a typo, that's the situation. 🚨

care must be taken when calling iv_tls_user_ptr from a signal handler, because there is a time window where it will return a non-NULL value before ->init_thread or after ->deinit_thread have been called. so the pointer can look valid while the state is, respectfully, mid-transition. πŸ’€

use of iv_tls for managing thread-local state is preferred over direct use of the __thread keyword, because not all platforms that ivykis runs on provide the __thread keyword. so like… portability. we love her. 🌈

use of iv_tls for managing thread-local state is also preferred over direct use of the pthread_key_create and pthread_setspecific APIs, because iv_tls provides a thread init hook as well as a destructor hook, and properly sequences ->init_thread and ->deinit_thread calls with core ivykis initialization and cleanup. that's the whole pitch. that's the point. 🧚


πŸ’œ SEE ALSO πŸ’œ


okay that's the whole page, bestie. you now know iv_tls better than half the people who call themselves systems programmers. periodt. πŸ’…

this was brought to you by ivykis, dated 2012-03-30, and yeah β€” the manual page is literally named iv_tls(3). mwah. 😘