linux - 线程一写多读的实验

前言

demo中,一个线程在写计数++, 另外一个线程在读, 算出tps。遇到了tps算不准的问题。
后来发现是分母上的时间差用秒为单位的缘故(1.5秒和2.4秒用2个time(NULL)减之后都是2秒)。换成微秒时间再乘以1000000就正常了。
开始一度想使用__sync_xx系列函数读取计数时,都同步一下。被同事指出这是在回避问题,尴尬…
其实,有问题时,各种实验都尝试一下。通过实验定位问题后,再解决就容易了。就像本次遇到的tps算不准的问题,如果尝试了__sync_xx后,肯定还是tps不准。那我就尝试下一个实验方法,这被扣上回避问题的帽子,也是真尴尬。只能说,如果开始尝试解决问题的方法对路,实验少做一些而已。

写了一个demo, 验证"一写多读"。实验证明,多个线程读值时,读到的都是写线程写的值,不会读到乱的值。

做这个实验,对linux线程的用法(传线程上下文, 线程启动,使用线程上下文,线程停止)复习了一次。使用linux线程时,设置线程上下文退出标记,让线程检测到退出标记后,自己退出。

找到一个参考资料,对linux线程的用法讲的特别细 => https://computing.llnl.gov/tutorials/pthreads/

demo下载点

src_test_time.7z

运行效果

Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.124 : remove_file()] : failed : remove [/var/log/test_time__file_flag_to_shutdown], error[-1] = [No such file or directory]
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.124 : remove_file()] : failed : remove [/var/log/test_time__file_flag_to_thread_run_all], error[-1] = [No such file or directory]
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.124 : remove_file()] : failed : remove [/var/log/test_time__file_flag_to_debug], error[-1] = [No such file or directory]
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.102 : main()] : MAKE_FILE_MACRO__BIN_NAME = [test_time]
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.460 : fn_test()] : >> fn_test()
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.462 : fn_test()] : l_cpu_numbers = 16
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.465 : fn_test()] : l_thread_numbers = 32
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[0] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[1] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[2] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[3] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.348 : thread_proc_write()] : >> thread_proc_write[0]
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[1], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[2], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[4] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[5] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[3], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[6] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[7] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[5], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[8] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[6], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[9] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[7], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[10] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[4], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[11], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[8], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[10], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[11] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[9], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[12] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[12], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[13] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[13], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[14] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[14], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[15] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[15], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[16] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[16], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[17] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[17], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[18], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[18] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[19] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[19], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[20] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[20], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[21] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[21], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[22], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[22] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[23] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[23], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[24], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[24] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[25] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[25], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[26] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[26], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[27] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[27], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[28] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[28], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[29] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[29], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[30] create
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.396 : thread_proc_read()] : >> thread_proc_read[30], wait FILE_FLAG_THREAD_RUN_ALL
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.280 : thread_proc_env_check()] : >> thread_proc_env_check[31]
Oct 16 06:02:59 debian8 test_time: [MY_LOGD : main.cpp.507 : fn_test()] : ok : pthread[31] create

...

Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.401 : thread_proc_read()] : >> thread_proc_read[5] find FILE_FLAG_THREAD_RUN_ALL, will be run
Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.353 : thread_proc_write()] : >> thread_proc_write[0] find FILE_FLAG_THREAD_RUN_ALL, will be run
Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.401 : thread_proc_read()] : >> thread_proc_read[10] find FILE_FLAG_THREAD_RUN_ALL, will be run
Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.401 : thread_proc_read()] : >> thread_proc_read[8] find FILE_FLAG_THREAD_RUN_ALL, will be run
Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.401 : thread_proc_read()] : >> thread_proc_read[13] find FILE_FLAG_THREAD_RUN_ALL, will be run
Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.401 : thread_proc_read()] : >> thread_proc_read[2] find FILE_FLAG_THREAD_RUN_ALL, will be run
Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.401 : thread_proc_read()] : >> thread_proc_read[1] find FILE_FLAG_THREAD_RUN_ALL, will be run
Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.401 : thread_proc_read()] : >> thread_proc_read[6] find FILE_FLAG_THREAD_RUN_ALL, will be run
Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.401 : thread_proc_read()] : >> thread_proc_read[9] find FILE_FLAG_THREAD_RUN_ALL, will be run
Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.401 : thread_proc_read()] : >> thread_proc_read[16] find FILE_FLAG_THREAD_RUN_ALL, will be run
Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.401 : thread_proc_read()] : >> thread_proc_read[4] find FILE_FLAG_THREAD_RUN_ALL, will be run
Oct 16 06:03:58 debian8 test_time: [MY_LOGD : main.cpp.401 : thread_proc_read()] : >> thread_proc_read[20] find FILE_FLAG_THREAD_RUN_ALL, will be run

...

Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[6] tps = 2013, ull_cnt_prev = 217230, ull_time_prev = 1539641149002014
Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[19] tps = 2013, ull_cnt_prev = 217231, ull_time_prev = 1539641149002510
Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[4] tps = 2014, ull_cnt_prev = 217232, ull_time_prev = 1539641149003070
Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[1] tps = 2012, ull_cnt_prev = 217233, ull_time_prev = 1539641149003532
Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[24] tps = 2012, ull_cnt_prev = 217233, ull_time_prev = 1539641149003512
Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[9] tps = 2013, ull_cnt_prev = 217234, ull_time_prev = 1539641149003998
Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[17] tps = 2012, ull_cnt_prev = 217236, ull_time_prev = 1539641149004498
Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[26] tps = 2013, ull_cnt_prev = 217238, ull_time_prev = 1539641149006115
Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[27] tps = 2014, ull_cnt_prev = 217238, ull_time_prev = 1539641149006145
Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[14] tps = 2013, ull_cnt_prev = 217239, ull_time_prev = 1539641149006304
Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[10] tps = 2013, ull_cnt_prev = 217239, ull_time_prev = 1539641149006256
Oct 16 06:05:50 debian8 test_time: [MY_LOGD : main.cpp.243 : calc_tps_and_show()] : thread[25] tps = 2013, ull_cnt_prev = 217240, ull_time_prev = 1539641149006591

...

Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.286 : thread_proc_env_check()] : thread_proc_env_check[31] recv quit command, stop other thread ...
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[0].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[1].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[2].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[3].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[4].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[5].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[6].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[7].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[8].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[9].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[10].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[11].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[12].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[13].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[14].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.362 : thread_proc_write()] : >> thread_proc_write[0] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.375 : thread_proc_write()] : << thread_proc_write[0]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[15].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[16].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[17].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[18].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[19].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[20].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[21].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[22].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[23].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[24].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[25].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[26].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[27].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[28].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[29].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.300 : thread_proc_env_check()] : set _p_ctx->p_thread_ctx_parent[30].b_request_quit_thread = true
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.313 : thread_proc_env_check()] : >> wait _p_ctx->p_thread_ctx_parent[1].h_thread end
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[11] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[4] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[11]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[4]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[22] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[22]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[12] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[12]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[19] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[19]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[18] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[18]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[9] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[9]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[13] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[13]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[25] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[25]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[21] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[21]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[26] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[26]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[15] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[15]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[10] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[10]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[20] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[20]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[6] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[6]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[16] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[16]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[1] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[1]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[24] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[24]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[23] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[23]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[5] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[5]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[30] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[30]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[29] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[29]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[17] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[17]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[27] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[27]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[2] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[2]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[28] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[28]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[3] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[3]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.315 : thread_proc_env_check()] : << wait _p_ctx->p_thread_ctx_parent[1].h_thread end
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.313 : thread_proc_env_check()] : >> wait _p_ctx->p_thread_ctx_parent[7].h_thread end
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[8] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[8]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[7] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[7]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.418 : thread_proc_read()] : >> thread_proc_read[14] find b_request_quit_thread, will be quit
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.431 : thread_proc_read()] : << thread_proc_read[14]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.315 : thread_proc_env_check()] : << wait _p_ctx->p_thread_ctx_parent[7].h_thread end
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.327 : thread_proc_env_check()] : << thread_proc_env_check[31]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.529 : fn_test()] : ok : stop thread_env_check
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.127 : remove_file()] : ok : remove [/var/log/test_time__file_flag_to_shutdown]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.127 : remove_file()] : ok : remove [/var/log/test_time__file_flag_to_thread_run_all]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.124 : remove_file()] : failed : remove [/var/log/test_time__file_flag_to_debug], error[-1] = [No such file or directory]
Oct 16 06:06:40 debian8 test_time: [MY_LOGD : main.cpp.110 : main()] : THE END


实验

// @file main.cpp
// @brief 测试时间取值(us)和计数(一写多读)
// @note 
// 	实验环境:
//	debian8.8
//
// 	调试:
// 	when debug, see log => tail -f /var/log/messages | grep MY_LOGD

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <pthread.h>

#include <string>

#include "const_define.h"

// 线程自己的私有数据
typedef struct _tag_thread_private_data {
	long l_tps; // 算出的当前tps值
	ull ull_time_prev; // 上一次记录tps的时间
	ull ull_cnt_prev; // 上一次记录的计数器值

	_tag_thread_private_data() {
		l_tps = 0;
		ull_time_prev = 0;
		ull_cnt_prev = 0;
	}
}TAG_THREAD_PRIVATE_DATA;

// 线程之间共享的数据
typedef struct _tag_thread_share_data {
	ull ull_cnt; // 一写多读的计数器

	_tag_thread_share_data() {
		ull_cnt = 0;
	}
}TAG_THREAD_SHARE_DATA;

// 线程上下文
typedef struct _tag_thread_context {
	bool b_init_h_thread; // h_thread is init ?
	pthread_t h_thread; // 线程句柄
	
	int i_thread_sn; // 线程号码

	_tag_thread_context* p_thread_ctx_parent; // 总的线程上下文, 用于环境检测线程停止其他线程
	long l_thread_numbers; // p_thread_ctx_parent 对应的线程数量(p_thread_ctx_parent[]的组数size)
	
	TAG_THREAD_SHARE_DATA* p_share_data; // 线程之间共享的数据结构
	TAG_THREAD_PRIVATE_DATA thread_private_data; // 线程的私有数据
	bool b_request_quit_thread; // 请求退出线程

	_tag_thread_context() {
		// h_thread = NULL; // pthread_t isn't pointer type, can't set to NULL
		b_init_h_thread = false;
		
		i_thread_sn = -1;

		p_thread_ctx_parent = NULL;
		l_thread_numbers = 0;

		p_share_data = NULL;
		b_request_quit_thread = false;
	}
} TAG_THREAD_CONTEXT;

void init(const char* psz_log_owner_name);
void uninit();
void proc_sig_term(int num);
int fn_test(int argc, char** argv);

bool is_file_exist(const char* psz_file_path_name, int& i_err_code, std::string& str_err_msg);
void read_and_show_context(TAG_THREAD_CONTEXT* p_ctx);
void write_and_show_context(TAG_THREAD_CONTEXT* p_ctx);
void show_ull_by_time(const char* psz_tip, ull ull_val);
void calc_tps_and_show(TAG_THREAD_CONTEXT* p_ctx);

void remove_flag_file();
void remove_file(const char* psz_file_path_name);

typedef void* (*PFN_thread_proc_env_check)(void* p_ctx);

void* thread_proc_env_check(void* p_ctx);
void* thread_proc_write(void* p_ctx);
void* thread_proc_read(void* p_ctx);

int main(int argc, char** argv)
{
    char sz_buf[MAX_MSG_LENGTH] = {'\0'};

#ifdef MAKE_FILE_MACRO__BIN_NAME
    sprintf(sz_buf, "%s", MAKE_FILE_MACRO__BIN_NAME);
    init(sz_buf);
    MYLOG_D("MAKE_FILE_MACRO__BIN_NAME = [%s]\n", MAKE_FILE_MACRO__BIN_NAME);
#else
    init(NULL);
#endif // #ifdef MAKE_FILE_MACRO__BIN_NAME

    fn_test(argc, argv);
    uninit();

    MYLOG_D("THE END\n");
    return EXIT_SUCCESS;
}

void remove_file(const char* psz_file_path_name)
{
	int i_rc = 0;
	
	if (NULL != psz_file_path_name) {
		i_rc = remove(psz_file_path_name);
		if (EOK != i_rc) {
			MYLOG_D("failed : remove [%s], error[%d] = [%s]\n",
				psz_file_path_name, 
				i_rc,
				strerror(errno));
		} else {
			MYLOG_D("ok : remove [%s]\n",
				psz_file_path_name);
		}
	}
}

void remove_flag_file()
{
	remove_file(FILE_FLAG_SHUTDOWN);
	remove_file(FILE_FLAG_THREAD_RUN_ALL);
	remove_file(FILE_FLAG_DEBUG);
}

void uninit()
{
	remove_flag_file();
}

void proc_sig_term(int num)
{
    MYLOG_D("SIGTERM = %d, num = %d\n", SIGTERM, num);
    MYLOG_D("maybe can do some clean task before quit\n");
    exit(1);	
}

void init(const char* psz_log_owner_name)
{
    int i = 0;

	MYLOG_D("%s\n", TITLE_LINE80);
	MYLOG_D("%s %s %s\n", 
		(NULL != psz_log_owner_name) ? psz_log_owner_name : "test_prog", 
		PROG_VER,
		RELEASE_TIME);

	MYLOG_D("%s\n", TITLE_LINE80);

    // daemon(0, 0);

    // clear screen (print 25 empty line)
    for (i = 0; i < 25; i++) {
        MYLOG_D("\n");
    }

    signal(SIGTERM, proc_sig_term);

	remove_flag_file();
}

bool is_file_exist(const char* psz_file_path_name, int& i_err_code, std::string& str_err_msg)
{
    bool b_rc = false;
    int i_rc = -1;

    do {
        if ((NULL == psz_file_path_name)
            || (0 == strlen(psz_file_path_name))) {
            i_err_code = -1;
            str_err_msg = "param 1 error";
            break;
        }

        i_rc = access(psz_file_path_name, F_OK);

        if (0 != i_rc) {
            i_err_code = errno;
            str_err_msg = strerror(i_err_code);
        } else {
            b_rc = true;
        }
    } while (0);

    return b_rc;
}

void show_ull_by_time(const char* psz_tip, ull ull_val)
{
	struct timeval tv_now;
	ull ull_time_now = 0;

	gettimeofday(&tv_now, NULL);
	ull_time_now = tv_now.tv_sec;
	ull_time_now *= 1000000;
	ull_time_now += tv_now.tv_usec;

	MYLOG_D("%s : ull_val = %llu, time now = %llu, %ld.%ld\n", 
		(NULL != psz_tip) ? psz_tip : "NULL",
		ull_val, 
		ull_time_now, 
		tv_now.tv_sec, 
		tv_now.tv_usec);
}

void calc_tps_and_show(TAG_THREAD_CONTEXT* p_ctx)
{
	struct timeval tv_now;
	ull ull_time_now = 0;
	ull ull_cnt_val_by_writer = 0;

	if (NULL != p_ctx) {
		gettimeofday(&tv_now, NULL);
		ull_time_now = tv_now.tv_sec;
		ull_time_now *= 1000000;
		ull_time_now += tv_now.tv_usec;

		ull_cnt_val_by_writer = p_ctx->p_thread_ctx_parent->p_share_data->ull_cnt;
		if ((p_ctx->thread_private_data.ull_cnt_prev > 0) 
			&& (p_ctx->thread_private_data.ull_time_prev > 0))
		{
			p_ctx->thread_private_data.l_tps = 
				1.0f * (ull_cnt_val_by_writer - p_ctx->thread_private_data.ull_cnt_prev) 
				/ (ull_time_now - p_ctx->thread_private_data.ull_time_prev) * 1000000;

			MYLOG_D("thread[%d] tps = %ld, ull_cnt_prev = %llu, ull_time_prev = %llu", 
				p_ctx->i_thread_sn, 
				p_ctx->thread_private_data.l_tps,
				p_ctx->thread_private_data.ull_cnt_prev,
				p_ctx->thread_private_data.ull_time_prev);
		}

		p_ctx->thread_private_data.ull_cnt_prev = ull_cnt_val_by_writer;
		p_ctx->thread_private_data.ull_time_prev = ull_time_now;
	}
}

void read_and_show_context(TAG_THREAD_CONTEXT* p_ctx)
{
	TAG_THREAD_CONTEXT* _p_ctx = (TAG_THREAD_CONTEXT*)p_ctx;

	if ((NULL != _p_ctx) && (NULL != _p_ctx->p_share_data)) {
		show_ull_by_time("rd", _p_ctx->p_share_data->ull_cnt);
	}
}

void write_and_show_context(TAG_THREAD_CONTEXT* p_ctx)
{
	TAG_THREAD_CONTEXT* _p_ctx = (TAG_THREAD_CONTEXT*)p_ctx;

	if ((NULL != _p_ctx) && (NULL != _p_ctx->p_share_data)) {
		_p_ctx->p_share_data->ull_cnt++;
		show_ull_by_time("wr", _p_ctx->p_share_data->ull_cnt);
	}
}

void* thread_proc_env_check(void* p_ctx)
{
	TAG_THREAD_CONTEXT* _p_ctx = (TAG_THREAD_CONTEXT*)p_ctx;
	int i = 0;

	do {
		if (NULL == _p_ctx) {
			break;
		}

		MYLOG_D(">> thread_proc_env_check[%d]\n", _p_ctx->i_thread_sn);

		do {
			if (_p_ctx->b_request_quit_thread) {
				// 等主线程来停止环境检测线程, 环境检测线程再去停止其他工作线程

				MYLOG_D("thread_proc_env_check[%d] recv quit command, stop other thread ...\n", _p_ctx->i_thread_sn);
				
				// close read thread
				// set quit command to all other thread
				for (i = 0; i < _p_ctx->l_thread_numbers; i++) {
					if (_p_ctx->p_thread_ctx_parent[i].i_thread_sn == _p_ctx->i_thread_sn) {
						// 这些线程也包含本线程, 只处理其他线程
						continue;
					}
					
					if (pthread_kill(_p_ctx->p_thread_ctx_parent[i].h_thread, 0) == 0) {
						// if thread is still active, first set thread quit falg
						// thread will quit by p_thread_ctx[i].b_request_quit_thread
						_p_ctx->p_thread_ctx_parent[i].b_request_quit_thread = true;
						MYLOG_D("set _p_ctx->p_thread_ctx_parent[%d].b_request_quit_thread = true\n", i);
					}
				}
				
				// wait all other thread over quit by them slef
				for (i = 0; i < _p_ctx->l_thread_numbers; i++) {
					if (_p_ctx->p_thread_ctx_parent[i].i_thread_sn == _p_ctx->i_thread_sn) {
						// 这些线程也包含本线程, 只处理其他线程
						continue;
					}
				
					if (pthread_kill(_p_ctx->p_thread_ctx_parent[i].h_thread, 0) == 0) {
						// then wait it exit
						MYLOG_D(">> wait _p_ctx->p_thread_ctx_parent[%d].h_thread end\n", i);
						pthread_join(_p_ctx->p_thread_ctx_parent[i].h_thread, NULL);
						MYLOG_D("<< wait _p_ctx->p_thread_ctx_parent[%d].h_thread end\n", i);
					}
				}
				
				break;
			}

			usleep(US_SLEEP_VAL_FO_READER);
		} while (1);
	} while (0);

	if (NULL != _p_ctx) {
		MYLOG_D("<< thread_proc_env_check[%d]\n", _p_ctx->i_thread_sn);
		pthread_exit((void*)(intptr_t)_p_ctx->i_thread_sn);
	} else {
		MYLOG_D("<< thread_proc_env_check\n");
		pthread_exit(NULL);
	}

	return NULL;
}

void* thread_proc_write(void* p_ctx)
{
	TAG_THREAD_CONTEXT* _p_ctx = (TAG_THREAD_CONTEXT*)p_ctx;
	int i_err_code = 0;
	std::string str_err = "";

	do {
		if (NULL == _p_ctx) {
			break;
		}

		MYLOG_D(">> thread_proc_write[%d]\n", _p_ctx->i_thread_sn);

		// wait thread run flag
		do {
			if (is_file_exist(FILE_FLAG_THREAD_RUN_ALL, i_err_code, str_err)) {
				MYLOG_D(">> thread_proc_write[%d] find FILE_FLAG_THREAD_RUN_ALL, will be run\n", _p_ctx->i_thread_sn);
				break;
			}

			usleep(US_SLEEP_VAL_FO_READER);
		} while (1);

		do {
			if (_p_ctx->b_request_quit_thread) {
				MYLOG_D(">> thread_proc_write[%d] find b_request_quit_thread, will be quit\n", _p_ctx->i_thread_sn);
				break;
			}

			// write_and_show_context(_p_ctx);
			_p_ctx->p_thread_ctx_parent->p_share_data->ull_cnt++;
			usleep(US_SLEEP_VAL_FO_WRITER); // 计数增加的频率远高于计数读的频率
		} while (1);

		
	} while (0);

	if (NULL != _p_ctx) {
		MYLOG_D("<< thread_proc_write[%d]\n", _p_ctx->i_thread_sn);
		pthread_exit((void*)(intptr_t)_p_ctx->i_thread_sn);
	} else {
		MYLOG_D("<< thread_proc_write\n");
		pthread_exit(NULL);
	}

	return NULL;
}

void* thread_proc_read(void* p_ctx)
{
	TAG_THREAD_CONTEXT* _p_ctx = (TAG_THREAD_CONTEXT*)p_ctx;
	int i_err_code = 0;
	std::string str_err = "";
	
	do {
		if (NULL == _p_ctx) {
			break;
		}

		MYLOG_D(">> thread_proc_read[%d], wait FILE_FLAG_THREAD_RUN_ALL\n", _p_ctx->i_thread_sn);

		// wait thread run flag
		do {
			if (is_file_exist(FILE_FLAG_THREAD_RUN_ALL, i_err_code, str_err)) {
				MYLOG_D(">> thread_proc_read[%d] find FILE_FLAG_THREAD_RUN_ALL, will be run\n", _p_ctx->i_thread_sn);
				break;
			}

			usleep(US_SLEEP_VAL_FO_READER);
		} while (1);

		do {
			if (1 == _p_ctx->i_thread_sn) {
				if (is_file_exist(FILE_FLAG_DEBUG, i_err_code, str_err)) {
					if (1 == _p_ctx->i_thread_sn) {
						MYLOG_D(""); // for debug #1 thread
					}
				}
			}
			
			if (_p_ctx->b_request_quit_thread) {
				MYLOG_D(">> thread_proc_read[%d] find b_request_quit_thread, will be quit\n", _p_ctx->i_thread_sn);
				break;
			}

			// read_and_show_context(_p_ctx);
			calc_tps_and_show(_p_ctx);
			
			usleep(US_SLEEP_VAL_FO_READER);
		} while (1);

	} while (0);

	if (NULL != _p_ctx) {
		MYLOG_D("<< thread_proc_read[%d]\n", _p_ctx->i_thread_sn);
		pthread_exit((void*)(intptr_t)_p_ctx->i_thread_sn);
	} else {
		MYLOG_D("<< thread_proc_read\n");
		pthread_exit(NULL);
	}

	return NULL;
}

// @ref https://computing.llnl.gov/tutorials/pthreads/
// POSIX Threads Programming

int fn_test(int argc, char** argv)
{
	bool b_rc = false;
	int i_err_code = 0;
	long l_cpu_numbers = 0;
	long l_thread_numbers = 0;
	std::string str_err = "";

	TAG_THREAD_CONTEXT* p_thread_ctx = NULL;
	TAG_THREAD_SHARE_DATA share_data;
	pthread_attr_t thread_attr;
	int i = 0;
	int i_thread_sn_env_check = 0; // 环境检测线程的号码

	PFN_thread_proc_env_check pfn_thread_proc_now = NULL;
	
    MYLOG_D(">> fn_test()\n");
	l_cpu_numbers = sysconf(_SC_NPROCESSORS_ONLN);
	MYLOG_D("l_cpu_numbers = %ld\n", l_cpu_numbers);

	l_thread_numbers = l_cpu_numbers * 2;
	MYLOG_D("l_thread_numbers = %ld\n", l_thread_numbers);

	pthread_attr_init(&thread_attr);
	pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);

	// create thread, 
	p_thread_ctx = new TAG_THREAD_CONTEXT[l_thread_numbers];
	for (i = 0; i < l_thread_numbers; i++) {
		p_thread_ctx[i].p_thread_ctx_parent = p_thread_ctx;
		p_thread_ctx[i].l_thread_numbers = l_thread_numbers;
		p_thread_ctx[i].p_share_data = &share_data;
		p_thread_ctx[i].i_thread_sn = i;
		if (i == (l_thread_numbers - 1)) {
			// 最后一个线程
			// 最后一个线程是检测线程(检测是否要退出, 如果检测操作放在主线程中, 优先级低, 没机会执行到检测代码)
			// 因为要操作其他线程句柄(e.g. 发现shutdown文件标志后), 如果shutdown文件已经存在,
			// 这种场景下, 如果其他线程还没创建,去操作其他无效的线程句柄,会崩溃(segment fault)
			pfn_thread_proc_now = thread_proc_env_check;
			i_thread_sn_env_check = i; // 保存管理线程的号码
		} else {
			switch (i) {
				// case 不能为变量...
				case 0: {
						// 1#线程是写线程, 
						pfn_thread_proc_now = thread_proc_write;
					}
					break;
				default: {
						// 其他线程是读线程
						pfn_thread_proc_now = thread_proc_read;
					}
					break;
			}
		}
		
		if (EOK == pthread_create(
			&p_thread_ctx[i].h_thread, 
			&thread_attr, 
			pfn_thread_proc_now, 
			p_thread_ctx + i))
		{
			p_thread_ctx[i].b_init_h_thread = true;
			MYLOG_D("ok : pthread[%d] create\n", p_thread_ctx[i].i_thread_sn);
		} else {
			MYLOG_D("error : pthread[%d] create : %s\n", p_thread_ctx[i].i_thread_sn, strerror(errno));
			break;
		}
	}
	
	do {
		if (is_file_exist(FILE_FLAG_SHUTDOWN, i_err_code, str_err)) {
			MYLOG_D("find shutdown file\n");

			pthread_attr_destroy(&thread_attr);

			// 停掉环境检测线程(环境检测线程负责停掉其他线程)
			if (pthread_kill(p_thread_ctx[i_thread_sn_env_check].h_thread, 0) == 0) {
				// if thread is still active, first set thread quit falg
				// thread will quit by p_thread_ctx[i_thread_sn_env_check].b_request_quit_thread
				p_thread_ctx[i_thread_sn_env_check].b_request_quit_thread = true;
				MYLOG_D("stop thread_env_check ...\n");
				pthread_join(p_thread_ctx[i_thread_sn_env_check].h_thread, NULL);
			}

			MYLOG_D("ok : stop thread_env_check\n");
			break;
		}

		// if not recv user quit command(/var/log/shutdown_test_time), run continue;
		usleep(US_SLEEP_VAL_FO_READER);
	} while (1);

	SAFE_DELETE_ARY(p_thread_ctx);

    return b_rc;
}


// @file const_define.h

#if not defined(__CONST_DEFINE_H__)
#define __CONST_DEFINE_H__

#include <string.h>
#include <string>
#include <list>
#include <syslog.h>

#define PROG_VER "1.0.0.1"
#define RELEASE_TIME "2018-11-11 14:04"

typedef unsigned long long ull;

#ifndef EOK
#define EOK 0
#endif // #ifndef EOK

#define MAX_MSG_LENGTH (1024 * 4)
	
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) \
    if (NULL != (p)) { \
        delete (p); \
        (p) = NULL; \
    }
#endif // #ifndef SAFE_DELETE

#ifndef SAFE_DELETE_ARY
#define SAFE_DELETE_ARY(p) \
    if (NULL != (p)) { \
        delete[] (p); \
        (p) = NULL; \
    }
#endif // #ifndef SAFE_DELETE

#define TITLE_LINE80 "================================================================================"
#define LINE80 "--------------------------------------------------------------------------------"

#if not defined(MYLOG_D)
#define MYLOG_D(fmt, ...) \
do { \
    syslog(LOG_INFO, "[%s : %s.%d : %s()] : " fmt, "MY_LOGD", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \
} while (0);
#endif // #if not defined(MYLOG_D)

#define FILE_FLAG_SHUTDOWN "/var/log/test_time__file_flag_to_shutdown"
#define FILE_FLAG_THREAD_RUN_ALL "/var/log/test_time__file_flag_to_thread_run_all"
#define FILE_FLAG_DEBUG "/var/log/test_time__file_flag_to_debug"

#define US_SLEEP_VAL_FO_WRITER 10 // 10微妙
#define US_SLEEP_VAL_FO_READER 1000000 // 1秒

#endif // #if not defined(__CONST_DEFINE_H__)


# ==============================================================================
# @file makefile
# ==============================================================================
# @note 
# howto build project
# 		make BIN_NAME="bin_name_by_you_want" rebuild
# makefile code need tab key not sapce key

MY_MAKE_FILE_PATH_NAME = $(MAKEFILE_LIST)

# macro from Makefile command line
# BIN_NAME

# macro to C project
MAKE_FILE_MACRO__BIN_NAME="make_file_macro__bin_name"

# var define on Makefile
BIN = output_not_give_bin_name
IS_BUILD_TYPE_VALID = 0

ifdef BIN_NAME
	IS_BUILD_TYPE_VALID = 1
	BIN = $(BIN_NAME)
	MAKE_FILE_MACRO__BIN_NAME=$(BIN_NAME)
else
	IS_BUILD_TYPE_VALID = 0
endif

LINE80 = --------------------------------------------------------------------------------

# CC = g++ -std=c++98
CC = g++

# -Werror is "warning as error"
CFLAGS = -Wall -Werror -g

INC = -I.
LIBPATH = -L/usr/lib/ -L/usr/local/lib/

ifeq (1, $(IS_BUILD_TYPE_VALID))
	LIBS = -lstdc++ -pthread
else
	LIBS =
endif

DEPEND_CODE_DIR = ../common/ \

DEPEND_CODE_SRC = $(shell find $(DEPEND_CODE_DIR) -name '*.cpp')
DEPEND_CODE_OBJ = $(DEPEND_CODE_SRC:.cpp=.o)

ROOT_CODE_SRC = $(shell find ./ -name '*.cpp')
ROOT_CODE_OBJ = $(ROOT_CODE_SRC:.cpp=.o)

SUB_CODE_DIR = ./empty_dir
SUB_CODE_SRC = $(shell find $(SUB_CODE_DIR) -name '*.cpp')
SUB_CODE_OBJ = $(SUB_CODE_SRC:.cpp=.o)

.PHONY: help
help:
	clear
	@echo "usage:"
	@echo
	@echo "build project by given bin name"
	@echo "make BIN_NAME=\"bin_name_by_you_want\" rebuild"
	@echo

.PHONY: clean
clean:
	clear

	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo

	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo

	@echo
	@echo
	@echo
	@echo
	@echo

	@echo "make clean begin"
	@echo $(LINE80)

	@echo "@file $(MY_MAKE_FILE_PATH_NAME)"
	@echo "IS_BUILD_TYPE_VALID = $(IS_BUILD_TYPE_VALID)"
	@echo "BIN = $(BIN)"

	@echo $(LINE80)

	rm -f $(ROOT_CODE_OBJ) $(DEPEND_CODE_OBJ) $(SUB_CODE_OBJ)

ifeq (1, $(IS_BUILD_TYPE_VALID))
	rm -f ./$(BIN)
endif

	@echo "make clean over"

.PHONY: all
all:$(BIN)
	@echo $(LINE80)
	@echo make all
	chmod 777 ./$(BIN)
	find . -name "$(BIN)"

$(BIN) : $(ROOT_CODE_OBJ) $(DEPEND_CODE_OBJ) $(SUB_CODE_OBJ)
	$(CC) $(CFLAGS) -o $@ $^ $(SHLIBS) $(INC) $(LIBPATH) $(LIBS)

.cpp.o:
	$(CC) -c $(CFLAGS) -DMAKE_FILE_MACRO__BIN_NAME="\"$(MAKE_FILE_MACRO__BIN_NAME)\"" $^ -o $@ $(INC) $(LIBPATH) $(LIBS)

.PHONY: rebuild
rebuild:
	make -f $(MY_MAKE_FILE_PATH_NAME) clean

ifeq (1, $(IS_BUILD_TYPE_VALID))
	@echo $(LINE80)
	make -f $(MY_MAKE_FILE_PATH_NAME) all
	chmod 775 ./$(BIN)
	ldd ./$(BIN)
else
	@echo $(LINE80)
	@echo "error : Makefile command line input error, please see help"	
	@echo "please run => make help"	
	@echo $(LINE80)
endif


#!/bin/bash
# ==============================================================================
# @file build_all_project.sh
# ==============================================================================

make BIN_NAME="test_time" rebuild


猜你喜欢

转载自blog.csdn.net/LostSpeed/article/details/83958640