time api
使用,定时器管理
clock_gettime
timespec_to_timeval
timeradd
timersub
timercmp
struct
enum
{
DSMCC_TIMEOUT_DSI,
DSMCC_TIMEOUT_DII,
DSMCC_TIMEOUT_MODULE,
DSMCC_TIMEOUT_NEXTBLOCK
};
struct dsmcc_timeout
{
struct dsmcc_object_carousel *carousel; /*< carousel this timeout applies to */
int type; /*< type of timeout */
uint16_t module_id; /*< module ID, for type == DSMCC_TIMEOUT_MODULE or DSMCC_TIMEOUT_NEXTBLOCK */
struct timeval abstime; /*< absolute time */
struct dsmcc_timeout *next;
};
add/remove
void dsmcc_timeout_remove(struct dsmcc_object_carousel *carousel, int type, uint16_t module_id)
{
struct dsmcc_timeout *current, *prev;
current = carousel->state->timeouts;
prev = NULL;
while (current)
{
int match = current->carousel == carousel && current->type == type;
if (type == DSMCC_TIMEOUT_MODULE || type == DSMCC_TIMEOUT_NEXTBLOCK)
match &= current->module_id == module_id;
if (match)
{
if (prev)
prev->next = current->next;
else
carousel->state->timeouts = current->next;
free(current);
return;
}
prev = current;
current = current->next;
}
}
void dsmcc_timeout_set(struct dsmcc_object_carousel *carousel, int type, uint16_t module_id, uint32_t delay_us)
{
struct dsmcc_timeout *timeout;
struct dsmcc_timeout *current, *next;
struct timeval now, delay;
struct timespec ts;
dsmcc_timeout_remove(carousel, type, module_id);
if (!delay_us)
return;
DSMCC_DEBUG("Adding timeout for carousel 0x%08x type %d module id 0x%04hhx delay %uus", carousel->cid, type, module_id, delay_us);
timeout = malloc(sizeof(struct dsmcc_timeout));
timeout->carousel = carousel;
timeout->type = type;
timeout->module_id = module_id;
clock_gettime(CLOCK_REALTIME, &ts);
timespec_to_timeval(&ts, &now);
delay.tv_sec = delay_us / 1000000;
delay.tv_usec = delay_us - delay.tv_sec * 1000000;
timeradd(&now, &delay, &timeout->abstime);
current = NULL;
next = carousel->state->timeouts;
while (next && timercmp(&next->abstime, &timeout->abstime, <))
{
current = next;
next = current->next;
}
timeout->next = next;
if (current)
current->next = timeout;
else
carousel->state->timeouts = timeout;
}
timer
struct dsmcc_timeout *prevtimeout, *timeout, *nexttimeout;
DSMCC_DEBUG("Current timeouts:");
timeout = state->timeouts;
prevtimeout = NULL;
while (timeout)
{
struct timeval curtime;
clock_gettime(CLOCK_REALTIME, &ts);
timespec_to_timeval(&ts, &curtime);
if (dsmcc_log_enabled(DSMCC_LOG_DEBUG))
{
struct timeval waittime;
timersub(&timeout->abstime, &curtime, &waittime);
DSMCC_DEBUG("CID 0x%08x DELAY %d.%06d TYPE %d MODULE_ID 0x%04hhx", timeout->carousel->cid, waittime.tv_sec, waittime.tv_usec,>
}
nexttimeout = timeout->next;
if (timercmp(&timeout->abstime, &curtime, <))
{
dsmcc_object_carousel_set_status(timeout->carousel, DSMCC_STATUS_TIMEDOUT);
dsmcc_filecache_notify_status(timeout->carousel, NULL);
/* remove timeout */
if (prevtimeout)
prevtimeout->next = timeout->next;
else
state->timeouts = timeout->next;
free(timeout);
}
timeout = nexttimeout;
}
api
头文件sys/time.h
定义
Unix/Linux
都是采用UTC(Universal Coordinated Time)
,1970.1.1
到现在的秒数,采用time_t(long int)
存储。
时间结构体包括time_t
, timeval
, time_spec
,精度越来越高
typedef long time_t
表示为从UTC(coordinated universal time)
时间1970 年 1 月 1 日 00 时 00 分 00 秒
( 也称为 Linux 系统的 Epoch 时间 ) 到当前时刻的秒数,只是精确到秒
struct timeval
{
time_t tv_sec; // 秒 s
long tv_usec;// 微秒 us
};
精确到微秒
struct timespec
{
long int tv_sec; // 秒 s
long int tv_nsec; // 纳秒 ns
};
精确到纳秒
clock_gettime
#include <time.h>
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
int clock_gettime(clockid_t clk_id, struct timespec *tp);
clk_id
常用:
CLOCK_REALTIME
, 系统实时时间,随系统实时时间改变而改变,即从UTC1970-1-1 0:0:0
开始计时,中间时刻如果系统时间被用户改成其他,则对应的时间相应改变CLOCK_MONOTONIC
, 从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
timespec_to_timeval
struct timespec
与struct timespec
之间的转换
/* Macros for converting between `struct timeval' and `struct timespec'. */
# define TIMEVAL_TO_TIMESPEC(tv, ts) { \
(ts)->tv_sec = (tv)->tv_sec; \
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
}
# define TIMESPEC_TO_TIMEVAL(tv, ts) { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
}
timeval 运算
在sys/time.h
中定义了如下运算
/* Convenience macros for operations on timevals.
NOTE: `timercmp' does not work for >= or <=. */
# define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
# define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
# define timercmp(a, b, CMP) \
(((a)->tv_sec == (b)->tv_sec) ? \
((a)->tv_usec CMP (b)->tv_usec) : \
((a)->tv_sec CMP (b)->tv_sec))
# define timeradd(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
if ((result)->tv_usec >= 1000000) \
{ \
++(result)->tv_sec; \
(result)->tv_usec -= 1000000; \
} \
} while (0)
# define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)