/********************************************************************************************** File name : ratelimit.h Module : common Author : Copyright : Version : 0.1 Created on : 2021-11-18 Creator : amir.liang Description : 以一定的速率执行入参函数, ratelimit(func()); 每次call这个调用,默认每5秒最多执行一次func() Modify History: 1. Date: Author: Modification: ************************************************************************************************/ #ifndef __RATELIMIT_H__ #define __RATELIMIT_H__ #include #include "htime.h" /** * 参考linux kernel的 printk_ratelimited * * 使用方法: * 默认5秒只执行1次 * ratelimit(printf("test\n")); * * * 设置成10秒可以执行30次 * ratelimit2(10, 30, printf("test\n")); */ struct ratelimit_state { //下面是运行时信息 uint32_t interval_ms; uint32_t next_ms; }; struct task_time_state { uint32_t task_start; uint32_t task_print_time; }; #define DEFAULT_RATELIMIT_INTERVAL 5 #define DEFAULT_RATELIMIT_BURST 1 //第2个版本,你也可以指定多少秒可以打印多少次 //ratelimit2(10, 30, printf("test\n")); #define ratelimit2(_sec, _times, _action) \ ({ \ static struct ratelimit_state _rs = { \ _sec*1000/_times, 0 \ }; \ uint32_t _now = gettimeofday_ms();\ if (_now >= _rs.next_ms){ \ _rs.next_ms = _now + _rs.interval_ms; \ _action; \ } \ }) //默认允许5秒打印1次log //ratelimit(printf("test\n")); #define ratelimit(_action) ratelimit2(DEFAULT_RATELIMIT_INTERVAL, 1, _action) //尝试times,直到action结果等于ifequ,每次延时delayms //do_retry2(action(), 10, 100, 0); 尝试10次action结果等于0时即退出,每次延时100ms #define do_retry2(_action, _times, _delayms, _ifequ_break)\ ({ \ int32_t _t = _times;\ while(_t-->0){\ if (_ifequ_break)\ break;\ ratelimit2(1, 5, printf("waiting %dms:%s\n", _delayms, #_action));\ usleep(_delayms*1000);\ }\ }) //默认延时100ms, action结果等于0时退出 //do_retry(action(), 10); 尝试10次,直到action结果等于0时即退出,每次延时100ms #define do_retry(_action, _times) do_retry2(_action, _times, 100, ==0) #define LOG_TIME2(_start_ts, _action) ({\ uint64_t pre_ts = _start_ts == -1 ? gettimeofday_ms() : _start_ts;\ _action;\ printf("%lu %s take:%llums\n", pre_ts, #_action, gettimeofday_ms() - pre_ts);\ }) /* * 计算某个函数或操作所消耗的时间 * _action, 可以是一个函数如: retalimit_delay() * _action, 可以是一个字符串: "imin" 用于时间打印记录 */ #define LOG_TIME(_action) LOG_TIME2(-1, _action) void retalimit_test(); #endif //__RATELIMIT_H__