600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > DELAY INIT 延迟初始化

DELAY INIT 延迟初始化

时间:2021-08-07 03:50:06

相关推荐

DELAY INIT 延迟初始化

全局变量,全局对象初始化,很方便。但过多的全局初始化,会导致程序启动时间过慢,还有全局初始化顺序不好控制(连接器可以可以控制文件之间的顺序,但那需要写好makefile, 并放映程序的实际依赖,没做到DRY).

我使用了内核的list_head 结构了组织初始化函数, 每个文件有一个file_node的结构来保持本文件内的初始化函数,file_node会注册的全局的一个分级数组中, file_node有个depend链表,保持了这个文件要依赖的其它文件。这样就实现了程序初始化顺序的管理。

delay_init.h

#ifndef __DELAY_INIT_H__

#define __DELAY_INIT_H__

#include "list.h"

namespace delay_init {

typedef int (*callback)(void);

struct file_node {

char const *file_name;

int called;

list_head init_list;

list_head depend_list;

list_head link_to_root;

};

#define DELAY_INIT_FILE_NODE_INIT(name) \

{\

__BASE_FILE__,\

0,\

LIST_HEAD_INIT(name.init_list),\

LIST_HEAD_INIT(name.depend_list),\

LIST_HEAD_INIT(name.link_to_root)\

}

#define DELAY_INIT_FILE_NODE(name) delay_init::file_node name = DELAY_INIT_FILE_NODE_INIT(name)

struct delay_init_struct {

list_head link_to_file;

callback init;

char const *info;

int called;

};

#define DELAY_INIT_STRUCT_INIT(name) \

{LIST_HEAD_INIT(name.link_to_file), 0, 0, 0}

#define DELAY_INIT_STRUCT(name) delay_init::delay_init_struct name=DELAY_INIT_STRUCT_INIT(name)

struct delay_init_depend_struct {

list_head link_to_depend;

file_node **point_file_node;

};

#define DELAY_INIT_DEPEND_STRUCT_INIT(name)\

{LIST_HEAD_INIT(name.link_to_depend), 0}

#define DELAY_INIT_DEPEND_STRUCT(name) delay_init::delay_init_depend_struct name = DELAY_INIT_DEPEND_STRUCT_INIT(name)

#define INIT_LEVEL_NUM 10

#define INIT_LOG_LEVEL 3

#define INIT_CONF_LEVEL 2

#define INIT_CONF_IOC_LEVEL 1

#define INIT_FIRST_LEVEL 0

#define INIT_LAST_LEVEL (INIT_LEVEL_NUM-1)

extern list_head g_delay_init_list_head[INIT_LEVEL_NUM];

int call_all_level();

int call_in_level(int level);

extern int failed_cnt;

extern int success_cnt;

extern int total_cnt;

extern int called_cnt;

}

#define MACRO_NAME_CONCAT2(a,b) MACRO_NAME_CONCAT2_PRITIVE(a,b)

#define MACRO_NAME_CONCAT2_PRITIVE(a,b) a##b

#define STRING_NAME(name) STRING_NAME_IMPL(name)

#define STRING_NAME_IMPL(name) #name

inline

int __one_call_call_fun__(void(*fun)(void)) {

fun();

return 1;

}

#define ONCE_CALL_FUNC(name) MACRO_NAME_CONCAT2(__func_once_call_ ,name)

#define ONCE_CALL_VAR(name) MACRO_NAME_CONCAT2(__var_once_call_, name)

#define ONCE_CALL_WITH(name) \

static void ONCE_CALL_FUNC(name)(void); \

static int ONCE_CALL_VAR(name) = __one_call_call_fun__(&ONCE_CALL_FUNC(name)); \

static void ONCE_CALL_FUNC(name)(void)

#define ONCE_CALL ONCE_CALL_WITH(MACRO_NAME_CONCAT2(__COUNTER__,__LINE__))

static DELAY_INIT_FILE_NODE(_this_file_node_delay_init_);

ONCE_CALL_WITH(delay_init_add_file_to_root)

{

list_add_tail(&_this_file_node_delay_init_.link_to_root,

&delay_init::g_delay_init_list_head[INIT_LAST_LEVEL]);

}

#define DELAY_INIT_IN_LEVEL(level) \

ONCE_CALL \

{\

list_move_tail(&_this_file_node_delay_init_.link_to_root, &delay_init::g_delay_init_list_head[level]);\

}

#define DELAY_INIT_NAME(name) MACRO_NAME_CONCAT2(MACRO_NAME_CONCAT2(__delay_init_def_, name), __LINE__)

#define DELAY_INIT \

static int DELAY_INIT_NAME(init_fun)(void); \

static DELAY_INIT_STRUCT(DELAY_INIT_NAME(init_node));\

ONCE_CALL { \

DELAY_INIT_NAME(init_node).init =&DELAY_INIT_NAME(init_fun);\

DELAY_INIT_NAME(init_node).info = \

"delay init name:" __FILE__ "_" STRING_NAME(__LINE__)\

" call in:" __FILE__ " line:" STRING_NAME(__LINE__); \

list_add_tail(&DELAY_INIT_NAME(init_node).link_to_file, &_this_file_node_delay_init_.init_list);\

return ;\

}\

static int DELAY_INIT_NAME(init_fun)(void)

#define DELAY_INIT_EXPORT_NAME(name) MACRO_NAME_CONCAT2(__delay_init_export_name_, name)

#define DELAY_INIT_EXPORT(name) \

delay_init::file_node * DELAY_INIT_EXPORT_NAME(name) = & _this_file_node_delay_init_;

#define DEPEND_ON_DELAY_INIT_NAME(name) MACRO_NAME_CONCAT2(name, MACRO_NAME_CONCAT2(__delay_init_depend_struct_, __LINE__))

#define DEPEND_ON_DELAY_INIT(name)\

extern delay_init::file_node * DELAY_INIT_EXPORT_NAME(name);\

static DELAY_INIT_DEPEND_STRUCT(DEPEND_ON_DELAY_INIT_NAME(_struct_));\

ONCE_CALL {\

DEPEND_ON_DELAY_INIT_NAME(_struct_).point_file_node = &DELAY_INIT_EXPORT_NAME(name);\

list_add_tail(&DEPEND_ON_DELAY_INIT_NAME(_struct_).link_to_depend, &_this_file_node_delay_init_.depend_list);\

}

#endif //__DELAY_INIT_H__

delay_init.cpp

#include "delay_init.h"

#include "repeat_macro.h"

#ifndef LOG

#define ENABLE_DELAY_INIT_CPP_LOG

#include <stdio.h>

#define LOG(level, format, ...)\

fprintf(stderr, "[%s][%s][%d]: " format "\n", #level, __FILE__, int(__LINE__), ##__VA_ARGS__)

#endif //LOG

namespace delay_init {

int failed_cnt = 0;

int success_cnt = 0;

int total_cnt = 0;

int called_cnt = 0;

#define INIT_LIST_HEAD_IMPL(s, index, name) COMMA_IF(index) LIST_HEAD_INIT(name[index])

#define LIST_HEAD_ARRAY_INIT(name, n) { EXPR(0)(REPEAT(0, n, INIT_LIST_HEAD_IMPL, name)) }

#define LIST_HEAD_ARRAY(name, n) list_head name[n] = LIST_HEAD_ARRAY_INIT(name, n)

LIST_HEAD_ARRAY(g_delay_init_list_head, INIT_LEVEL_NUM);

static int call_file_list(file_node *file_list) {

if (file_list->called) {

return 0;

}

LOG(DEBUG, "delay_init in file: %s", file_list->file_name);

int ret = 0;

list_head *q = NULL;

list_for_each(q, &file_list->depend_list) {

delay_init_depend_struct *depend =

container_of(q, delay_init_depend_struct, link_to_depend);

if (*(depend->point_file_node)) {

ret += call_file_list(*(depend->point_file_node));

}

}

list_for_each(q, &file_list->init_list) {

delay_init_struct *st =

container_of(q, delay_init_struct, link_to_file);

callback init = st->init;

if (init) {

if (0 == st->called) {

LOG(DEBUG, "call delay init func:%s", st->info);

ret += init();

++st->called;

++called_cnt;

}

++success_cnt;

} else {

++failed_cnt;

}

++total_cnt;

}

++(file_list->called);

return ret;

}

int call_in_level(int level) {

if (level < 0 || INIT_LEVEL_NUM - 1 < level) {

LOG(ERROR, "error init level [%d] group", level);

return -1;

}LOG(DEBUG, "delay_init in level: %d", level);

int ret = 0;

list_head *q = NULL;

list_for_each(q, &g_delay_init_list_head[level]) {

file_node * file_list = container_of(q, file_node, link_to_root);

ret += call_file_list(file_list);

}

return ret;

}

int call_all_level() {

int ret = 0;

for (int i = 0; i < INIT_LEVEL_NUM; ++i) {

ret += call_in_level(i);

}

return ret;

}

}

#ifdef ENABLE_DELAY_INIT_CPP_LOG

#undef LOG

#undef ENABLE_DELAY_INIT_CPP_LOG

#endif //ENABLE_DELAY_INIT_CPP_LOG

使用范例

log.h

#ifndef __LOG_IMPL__

DEPEND_ON_DELAY_INIT(log)

#endif //__LOG_IMPL__

这样,所有使用了 log.h的程序,都会先初始化好log

log.cpp

#define __LOG_IMPL__

#include "log.h"

…….

DELAY_INIT

{

……

}

DELAY_INIT_EXPORT(log)

main.cpp

delay_init::call_all_level();

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。