Repository: valkey-io/valkey
File: src/bio.c (C)

Code before:

typedef struct {
    const char *const bio_worker_title;
    pthread_t bio_thread_id;
    pthread_mutex_t bio_mutex;
    pthread_cond_t bio_newjob_cond;
    list *bio_jobs;
} bio_worker_data;

static bio_worker_data bio_workers[] = {
    {"bio_close_file"},
    {"bio_aof"},
    {"bio_lazy_free"},
    {"bio_rdb_save"}};
static const bio_worker_data *const bio_worker_end = bio_workers + (sizeof bio_workers / sizeof *bio_workers);
#define BIO_WORKER_NUM(X) ((X) - bio_workers)

static unsigned long bio_jobs_counter[BIO_NUM_OPS] = {0};
static _Thread_local size_t bio_worker_num = 0;

/* This structure represents a background Job. It is only used locally to this
 * file as the API does not expose the internals at all. */
typedef union bio_job {
    struct {
        int type; /* Job-type tag. This needs to appear as the first element in all union members. */
    } header;

    /* Job specific arguments.*/
    struct {
        int type;
        int fd;                          /* Fd for file based background jobs */
        long long offset;                /* A job-specific offset, if applicable */
        unsigned need_fsync : 1;         /* A flag to indicate that a fsync is required before
                                          * the file is closed. */
        unsigned need_reclaim_cache : 1; /* A flag to indicate that reclaim cache is required before
                                          * the file is closed. */
    } fd_args;

    struct {
        int type;
        lazy_free_fn *free_fn; /* Function that will free the provided arguments */
        void *free_args[];     /* List of arguments to be passed to the free function */
    } free_args;

    struct {
        int type;
        connection *conn;    /* Connection to download the RDB from */
        int is_dual_channel; /* Single vs dual channel */
    } save_to_disk_args;
} bio_job;


Review comment (refactor):
I like the use of c11 thread local. maybe we should use this PR to also replace all the existing __thread uses (not many) as we are c11 compatible and although we do only support gcc/clang it would be nice to remove this dependency 

Code after:

typedef struct {
    const char *const bio_worker_title;
    pthread_t bio_thread_id;
    pthread_mutex_t bio_mutex;
    pthread_cond_t bio_newjob_cond;
    list *bio_jobs;
} bio_worker_data;

static bio_worker_data bio_workers[] = {
    {"bio_close_file"},
    {"bio_aof"},
    {"bio_lazy_free"},
    {"bio_rdb_save"},
};
static const bio_worker_data *const bio_worker_end = bio_workers + (sizeof bio_workers / sizeof *bio_workers);

static size_t bioWorkerNum(const bio_worker_data *const bwd) {
    /* Ensure the pointer is valid - casting to uintptr_t to not make the comparison itself UB in case
     * the pointer is outside the valid range. It's a best effort thing anyway. */
    serverAssert((uintptr_t)bwd >= (uintptr_t)bio_workers && (uintptr_t)bwd < (uintptr_t)bio_worker_end);
    return (size_t)(bwd - bio_workers);
}

static unsigned long bio_jobs_counter[BIO_NUM_OPS] = {0};
static _Thread_local size_t bio_worker_num = 0;

/* This structure represents a background Job. It is only used locally to this
 * file as the API does not expose the internals at all. */
typedef union bio_job {
    struct {
        int type; /* Job-type tag. This needs to appear as the first element in all union members. */
    } header;

    /* Job specific arguments.*/
    struct {
        int type;
        int fd;                          /* Fd for file based background jobs */
        long long offset;                /* A job-specific offset, if applicable */
        unsigned need_fsync : 1;         /* A flag to indicate that a fsync is required before
                                          * the file is closed. */
        unsigned need_reclaim_cache : 1; /* A flag to indicate that reclaim cache is required before
                                          * the file is closed. */
    } fd_args;

    struct {
        int type;
        lazy_free_fn *free_fn; /* Function that will free the provided arguments */
        void *free_args[];     /* List of arguments to be passed to the free function */
    } free_args;