mirror of https://gitlab.freedesktop.org/mesa/mesa
72 lines
1.7 KiB
C
72 lines
1.7 KiB
C
/*
|
|
* Copyright 2022 Yonggang Luo
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
* Extend C11 call_once to support context parameter
|
|
*/
|
|
|
|
#ifndef U_CALL_ONCE_H_
|
|
#define U_CALL_ONCE_H_
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "c11/threads.h"
|
|
#include "macros.h"
|
|
#include "u_atomic.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* The data can be mutable or immutable. */
|
|
typedef void (*util_call_once_data_func)(const void *data);
|
|
|
|
struct util_once_flag {
|
|
bool called;
|
|
once_flag flag;
|
|
};
|
|
typedef struct util_once_flag util_once_flag;
|
|
|
|
#define UTIL_ONCE_FLAG_INIT { false, ONCE_FLAG_INIT }
|
|
|
|
/**
|
|
* This is used to optimize the call to call_once out when the func are
|
|
* already called and finished, so when util_call_once are called in
|
|
* hot path it's only incur an extra load instruction cost.
|
|
*/
|
|
static ALWAYS_INLINE void
|
|
util_call_once(util_once_flag *flag, void (*func)(void))
|
|
{
|
|
if (unlikely(!p_atomic_read_relaxed(&flag->called))) {
|
|
call_once(&flag->flag, func);
|
|
p_atomic_set(&flag->called, true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Wrapper around call_once to pass data to func
|
|
*/
|
|
void
|
|
util_call_once_data_slow(once_flag *once, util_call_once_data_func func, const void *data);
|
|
|
|
/**
|
|
* This is used to optimize the call to util_call_once_data_slow out when
|
|
* the func function are already called and finished,
|
|
* so when util_call_once_data are called in hot path it's only incur an extra
|
|
* load instruction cost.
|
|
*/
|
|
static ALWAYS_INLINE void
|
|
util_call_once_data(util_once_flag *flag, util_call_once_data_func func, const void *data)
|
|
{
|
|
if (unlikely(!p_atomic_read_relaxed(&flag->called))) {
|
|
util_call_once_data_slow(&(flag->flag), func, data);
|
|
p_atomic_set(&flag->called, true);
|
|
}
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* U_CALL_ONCE_H_ */
|