概要
grpc有自己的一套时间管理接口time.h,实现了时间的获取及转化;下面了解下time.h的时间管理接口:
核心结构
首先介绍下时间相关的核心结构:
时钟类型
typedef enum {
/** 单调的时钟:没有固定的起点或终点,时间点始终向前推进。通常用于表示系统的时间进度,与系统时钟相比,更加稳定,不受系统时间变化的影响,可以用于计算时间间隔或时间戳等操作。 */
GPR_CLOCK_MONOTONIC = 0,
/** 实时时钟:可以向前或向后跳跃,并且可以由系统管理员设置。它的起点是1970年1月1日0时0分0秒(UTC时间),因此它的时标是相对于这个起点计算的。 */
GPR_CLOCK_REALTIME,
/** 精确时钟:这种时钟是通过x86平台上的rdtsc指令获取的CPU周期时间。在其他平台上,它的精确度会降低,成为GPR_CLOCK_REALTIME的替代品。 */
GPR_CLOCK_PRECISE,
/** 不可测量的时钟:这种时钟类型没有基准,是通过计算两个时间之间的差值来得到的。*/
GPR_TIMESPAN
} gpr_clock_type;
时间结构
typedef struct gpr_timespec {
int64_t tv_sec; //秒
int32_t tv_nsec; //纳秒
gpr_clock_type clock_type;//时钟类型
} gpr_timespec;
核心方法
时间常数
// 0时间间隔
GPRAPI gpr_timespec gpr_time_0(gpr_clock_type type);
// 无穷大,未来时间点
GPRAPI gpr_timespec gpr_inf_future(gpr_clock_type type);
// 无穷小,过去时间点
GPRAPI gpr_timespec gpr_inf_past(gpr_clock_type type);
//代码实现如下:
gpr_timespec gpr_time_0(gpr_clock_type type) {
gpr_timespec out;
out.tv_sec = 0;
out.tv_nsec = 0;
out.clock_type = type;
return out;
}
gpr_timespec gpr_inf_future(gpr_clock_type type) {
gpr_timespec out;
out.tv_sec = INT64_MAX;
out.tv_nsec = 0;
out.clock_type = type;
return out;
}
gpr_timespec gpr_inf_past(gpr_clock_type type) {
gpr_timespec out;
out.tv_sec = INT64_MIN;
out.tv_nsec = 0;
out.clock_type = type;
return out;
}
这是三个极端时间点。
gpr_time_0一般作为计时的起点或者比较时间的基准,可以用于一些初始化或比较操作中;
gpr_inf_past/gpr_inf_future: 可以用来设置异步API的deadline参数,代表永不超时;
初始化时间子系统
GPRAPI void gpr_time_init(void);
该接口用于windows,不做解释。
获取当前时间
GPRAPI gpr_timespec gpr_now(gpr_clock_type clock);
描述:
返回由给定时钟纪元测量的当前时间
参数:
clock:时钟类型
注:clock的时钟类型不能为GPR_TIMESPAN;
GPRAPI gpr_timespec gpr_convert_clock_type(gpr_timespec t,
gpr_clock_type clock_type);
描述:
将一个时钟类型转换为另一个时钟类型
参数:
t : 要转换的时钟
clock_type:想要转换的目的时钟类型
示例代码:
gpr_timespec timeVal = gpr_now(GPR_CLOCK_REALTIME);
gpr_timespec val = gpr_convert_clock_type(timeVal, GPR_CLOCK_PRECISE);//将timeVal 从GPR_CLOCK_REALTIME转化为GPR_CLOCK_PRECISE类型的时间值
时间比较
GPRAPI int gpr_time_cmp(gpr_timespec a, gpr_timespec b);
GPRAPI gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b);
GPRAPI gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b);
描述:
比较两个时间的大小:
gpr_time_cmp:比较a,b两个时间值,a>b:返回1, a=b:返回0,agpr_time_max:返回a,b中较大的值
gpr_time_min:返回a,b中较小的值
参数:
a,b:两个时间值
注:比较的两个时间值的时钟类型必须一样。
时间计算
GPRAPI gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b);
GPRAPI gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b);
描述:
计算a,b两个时间的和或者差:
gpr_time_add:返回a+b的时间值
gpr_time_sub:返回a-b的时间值
参数:
a,b:两个时间值
注:参数b的时钟类型必须为GPR_TIMESPAN。
时间间隔
GPRAPI gpr_timespec gpr_time_from_micros(int64_t us, gpr_clock_type clock_type);//微秒
GPRAPI gpr_timespec gpr_time_from_nanos(int64_t ns, gpr_clock_type clock_type);//纳秒
GPRAPI gpr_timespec gpr_time_from_millis(int64_t ms, gpr_clock_type clock_type);//毫秒
GPRAPI gpr_timespec gpr_time_from_seconds(int64_t s, gpr_clock_type clock_type);//秒
GPRAPI gpr_timespec gpr_time_from_minutes(int64_t m, gpr_clock_type clock_type);//分钟
GPRAPI gpr_timespec gpr_time_from_hours(int64_t h, gpr_clock_type clock_ty
描述:
将给定的时间值转化为gpr_timespec结构体,在实际应用中用作时间间隔。
例:
gpr_time_from_micros为微秒级别,则第一个参数的数值代表多少微秒,一般情况下联合使用gpr_now和这类函数进行超时设置。
参数:
第一个参数:对应级别的时间值
clock_type:时钟类型
为什么说这类函数一般用于时间间隔,看下面的例子:
void *tag = nullptr;
bool ok;
gpr_timespec timeVal = gpr_now(GPR_CLOCK_REALTIME);
gpr_timespec def = gpr_time_add(timeVal, gpr_time_from_millis(10000, GPR_TIMESPAN));
AsyncNext(&tag, &ok, def);//设置超时为10s,10s内没有响应的话就返回。
与时间间隔相反,有如下函数:
GPRAPI int32_t gpr_time_to_millis(gpr_timespec timespec);
该函数将gpr_timespec结构的时间值,转化为整型毫秒值。
其他
范围比较
GPRAPI int gpr_time_similar(gpr_timespec a, gpr_timespec b,
gpr_timespec threshold);
描述:
如果a,b相等或者在threshold阈值范围内(a,b的差值不超过threshold)返回1,否则返回0;
参数:
a,b:要比较的两个时间值
threshold:阈值
注:a,b的时钟类型必须一样,threshold的时钟类型必须是GPR_TIMESPAN类型。
睡眠
GPRAPI void gpr_sleep_until(gpr_timespec until);
描述:
类似于c语言的sleep,延时某个时间。
参数:
until:要延时的时间
获取微妙值
GPRAPI double gpr_timespec_to_micros(gpr_timespec t);
描述:
将gpr_timespec类型的时间值转化为double类型的微秒值。