> For the complete documentation index, see [llms.txt](https://hitzhangjie.gitbook.io/libmill/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hitzhangjie.gitbook.io/libmill/timer/libmill-timer.md).

# 定时器: timer

**1 timer.h**

```c
struct mill_timer {
    // mill_list_item结合mill_cont来实现了list iterator
    /* Item in the global list of all timers. */
    struct mill_list_item item;
    /* The deadline when the timer expires. -1 if the timer is not active. */
    int64_t expiry;
    /* Callback invoked when timer expires. Pfui Teufel! */
    mill_timer_callback callback;
};
```

```c
/* Test wheather the timer is active. */
#define mill_timer_enabled(tm)  ((tm)->expiry >= 0)

/* Add a timer for the running coroutine. */
void mill_timer_add(struct mill_timer *timer, int64_t deadline, mill_timer_callback callback);

/* Remove the timer associated with the running coroutine. */
void mill_timer_rm(struct mill_timer *timer);

/* Number of milliseconds till the next timer expires. If there are no timers returns -1. */
int mill_timer_next(void);

/* Resumes all coroutines whose timers have already expired. Returns zero if no coroutine was resumed, 1 otherwise. */
int mill_timer_fire(void);

/* Called after fork in the child process to deactivate all the timers inherited from the parent. */
void mill_timer_postfork(void);
```

**2 timer.c**

```c
// 定时器精度控制，rdtsc先后读取ticks差值超过这个值则gettimeofday更新last_now
#define MILL_CLOCK_PRECISION 1000000
```

```c
// 返回gettimeofday获取的系统时间，单位seconds
static int64_t mill_os_time(void) {
#if defined __APPLE__
    ...
#else
    struct timeval tv;
    int rc = gettimeofday(&tv, NULL);
    assert(rc == 0);
    return ((int64_t)tv.tv_sec) * 1000 + (((int64_t)tv.tv_usec) / 1000);
#endif
}
```

```c
// 获取当前系统时间（注意这里的时间是有cache的）
int64_t mill_now_(void) {
#if (defined __GNUC__ || defined __clang__) && (defined __i386__ || defined __x86_64__)
    // rdtsc获取系统启动后经历的cpu时钟周期数量
    uint32_t low;
    uint32_t high;
    __asm__ volatile("rdtsc" : "=a" (low), "=d" (high));

    int64_t tsc = (int64_t)((uint64_t)high << 32 | low);

    static int64_t last_tsc = -1;
    static int64_t last_now = -1;
    if(mill_slow(last_tsc < 0)) {
        last_tsc = tsc;
        last_now = mill_os_time();
    }
    // 如果在精度范围内返回上次获取的系统时间，超出精度范围则更新系统时间
    if(mill_fast(tsc - last_tsc <= (MILL_CLOCK_PRECISION / 2) && tsc >= last_tsc))
        return last_now;

    last_tsc = tsc;
    last_now = mill_os_time();
    return last_now;
#else
    return mill_os_time();
#endif
}
```

```c
// 定时器列表，列表中定时器是有序的，时间靠前的排列在前面
static struct mill_list mill_timers = {0};

// 往定时器列表中添加定时器，保证链表中定时器有序（按过期时间升序排列）
void mill_timer_add(struct mill_timer *timer, int64_t deadline, mill_timer_callback callback) {
    mill_assert(deadline >= 0);
    timer->expiry = deadline;
    timer->callback = callback;
    /* Move the timer into the right place in the ordered list
       of existing timers. TODO: This is an O(n) operation! */
    struct mill_list_item *it = mill_list_begin(&mill_timers);
    while(it) {
        struct mill_timer *tm = mill_cont(it, struct mill_timer, item);
        /* If multiple timers expire at the same momemt they will be fired
           in the order they were created in (> rather than >=). */
        if(tm->expiry > timer->expiry)
            break;
        it = mill_list_next(it);
    }
    mill_list_insert(&mill_timers, &timer->item, it);
}

// 从定时器列表中移除定时器
void mill_timer_rm(struct mill_timer *timer) {
    mill_assert(timer->expiry >= 0);
    mill_list_erase(&mill_timers, &timer->item);
    timer->expiry = -1;
}

// 返回定时器列表中首个定时器的剩余超时时间
int mill_timer_next(void) {
    if(mill_list_empty(&mill_timers))
        return -1;
    int64_t nw = now();
    int64_t expiry = mill_cont(mill_list_begin(&mill_timers), struct mill_timer, item) -> expiry;
    return (int) (nw >= expiry ? 0 : expiry - nw);
}

// 执行所有超时的定时器绑定的回调函数，返回是否有调用定时器的回调方法
int mill_timer_fire(void) {
    /* Avoid getting current time if there are no timers anyway. */
    if(mill_list_empty(&mill_timers))
        return 0;
    int64_t nw = now();
    int fired = 0;
    while(!mill_list_empty(&mill_timers)) {
        struct mill_timer *tm = mill_cont(
            mill_list_begin(&mill_timers), struct mill_timer, item);
        if(tm->expiry > nw)
            break;
        mill_list_erase(&mill_timers, mill_list_begin(&mill_timers));
        tm->expiry = -1;
        if(tm->callback)
            tm->callback(tm);
        fired = 1;
    }
    return fired;
}

// 初始化定时器列表（postfork？fixme!!!）
void mill_timer_postfork(void) {
    mill_list_init(&mill_timers);
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hitzhangjie.gitbook.io/libmill/timer/libmill-timer.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
