Linux多定时器实现之二

Linux多定时器实现之二

本文为多定时器的工业级实现,实现了秒级的多定时器,时间复杂度近似O(1)。具有以下特点:

  • 新建定时器的时间复杂度降近似为O(1)。它根据定时器的超时值,将新定时器散列到hash桶中
  • 删除定时器的时间复杂度近似为O(1)
  • 能用于多线程环境

多定时器的C语言代码:

/***********************************************************************
* Copyright (c) 2018 pepstack, pepstack.com
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
*   claim that you wrote the original software. If you use this software
*   in a product, an acknowledgment in the product documentation would be
*   appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
*   be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
***********************************************************************/

/**
 * mul_wheel_timer.h
 *   multi wheel timer for linux
 *
 *   秒级多定时器的工业级实现
 *
 * refer:
 *   http://blog.csdn.net/zhangxinrun/article/details/5914191
 *   https://linux.die.net/man/2/setitimer
 *
 * author: [email protected]
 *
 * create: 2018-02-03 11:00
 * update: 2018-02-03 22:09
 */
#ifndef MUL_WHEEL_TIMER_H_INCLUDED
#define MUL_WHEEL_TIMER_H_INCLUDED

#if defined(__cplusplus)
extern "C"
{
#endif

#include "dhlist.h"

#include <pthread.h>
#include <unistd.h>

#include <time.h>
#include <sys/time.h>


/**
 * 是否使用双链表:如果不需要按次序遍历定时器不要启用它
 *
 * MUL_WHEEL_TIMER_HAS_DLIST == 1
 *   use dlist for traversing by sequence
 *
 * MUL_WHEEL_TIMER_HAS_DLIST == 0
 *   DONOT use dlist since we need not traversing by sequence
 */
#define MUL_WHEEL_TIMER_HAS_DLIST   0


/**
 * MUL_WHEEL_TIMER_HASHLEN_MAX
 *
 * 定义 hash 桶的大小 (2^n -1) = [255, 1023, 4095, 8191]
 * 可以根据需要在编译时指定。桶越大,查找速度越快。
 */
#ifndef MUL_WHEEL_TIMER_HASHLEN_MAX
#  define MUL_WHEEL_TIMER_HASHLEN_MAX     1023
#endif


/**
 * MUL_WHEEL_TIMER_TIMEUNIT_SEC
 *
 * 定义多定时器的时间单位:即最小时间间隔。系统将按照这个时间间隔定时激发
 * 定时器回调函数:sigalarm_handler
 */
#ifndef MUL_WHEEL_TIMER_TIMEUNIT_SEC
#  define MUL_WHEEL_TIMER_TIMEUNIT_SEC    1
#endif


#define MUL_WHEEL_TIMER_TIMEUNIT_DEFAULT   (-1)

typedef int64_t mul_eventid_t;

typedef mul_eventid_t * mul_event_handle;


typedef struct mul_timer_event_t
{
    mul_eventid_t eventid;

    /* 引用计数: 0 删除, 1 保留 */
    int refc;

    void *eventarg;
    int (*timer_event_cb) (mul_event_handle eventhdl, void *eventarg);

    int64_t on_counter;

    /* 指定定时器首次激发时间和以后每次间隔激发时间 */
    struct itimerval value;

    unsigned int timeout;

    int hash;

    /** dhlist node */
#if MUL_WHEEL_TIMER_HAS_DLIST == 1
    struct list_head  i_list;
#endif
    struct hlist_node i_hash;
} mul_timer_event_t;


typedef struct mul_wheel_timer_t
{
    pthread_mutex_t lock;

    /**
     * 定时器状态:
     *    1: 启动
     *    0: 暂停
     */
    int status;

    volatile mul_eventid_t eventid;

    volatile int64_t counter;

    void (* old_sigalarm)(int);
    void (* new_sigalarm)(int);

    unsigned int timeunit;

    struct itimerval value, ovalue;

    /** dhlist for timer entry */
#if MUL_WHEEL_TIMER_HAS_DLIST == 1
    struct list_head dlist;
#endif
    struct hlist_head hlist[MUL_WHEEL_TIMER_HASHLEN_MAX + 1];
} mul_wheel_timer_t;


/* global timer variable for one linux process */
__attribute__((used))
static struct mul_wheel_timer_t  mulwheeltimer;


__attribute__((used))
static void sigalarm_handler(int signo);


__attribute__((used))
static inline void free_timer_event (struct mul_timer_event_t * event)
{
    printf("\033[32m-delete event_%llu\033[0m\n", (unsigned long long) event->eventid);
    free(event);
}


__attribute__((used))
static inline mul_timer_event_t * mul_handle_cast_event (mul_event_handle eventhdl)
{
    struct mul_timer_event_t * event = CONTAINER_OF(eventhdl, struct mul_timer_event_t, eventid);
    return event;
}


__attribute__((used))
static int64_t timer_on_counter_hash (mul_wheel_timer_t * mwtr, unsigned int tv_sec, int *hash)
{
    int64_t on_counter = (int64_t) (tv_sec / mwtr->timeunit + mwtr->counter);
    *hash = (on_counter & MUL_WHEEL_TIMER_HASHLEN_MAX);

    printf(" * \033[36mon_counter=%lld, hash=%d\033[0m\n", (long long) on_counter, (*hash));
    return on_counter;
}


__attribute__((used))
static int timer_select_sleep (int sec, int ms)
{
    if (sec || ms) {
        struct timeval tv = {0};

        tv.tv_sec = sec;
        tv.tv_usec =ms*1000;

        return select (0, NULL, NULL, NULL, &tv);
    } else {
        return 0;
    }
}


/**
 * mul_wheel_timer_create
 *
 *  根据给定值初始化多定时器。本程序不提供秒以下的定时器,如果需要请用户自行扩充。
 *
 * params:
 *   start - 1: 立即启动定时器; 0: 不启动定时器
 *
 *  1) 初始化最小时间单位 (= MUL_WHEEL_TIMER_TIMEUNIT_SEC) 秒的多定时器:
 *
 *      mul_wheel_timer_create(MUL_WHEEL_TIMER_TIMEUNIT_DEFAULT, 0);
 *
 *  2) 初始化最小时间单位 (= 10) 秒的多定时器,且在60秒以后开始启用, 启用
 *     之后每隔 10 秒激发 1 次:
 *
 *      mul_wheel_timer_create(10, 60);
 *
 * returns:
 *    0: success
 *   -1: failed.
 *      use strerror(errno) for error message.
 */
__attribute__((used))
static int mul_wheel_timer_create (long timeunit_sec, long timedelay_sec, int start)
{
    int i, err;

    bzero(&mulwheeltimer, sizeof(struct mul_wheel_timer_t));

    mulwheeltimer.eventid = 1;

#if MUL_WHEEL_TIMER_HAS_DLIST == 1
    INIT_LIST_HEAD(&mulwheeltimer.dlist);
#endif
    for (i = 0; i <= MUL_WHEEL_TIMER_HASHLEN_MAX; i++) {
        INIT_HLIST_HEAD(&mulwheeltimer.hlist[i]);
    }

    err = pthread_mutex_init(&mulwheeltimer.lock, 0);
    if (err) {
        /* nerver run to this ! */
        return (-1);
    }

    err = pthread_mutex_lock(&mulwheeltimer.lock);
    if (err) {
        printf("[mwt] pthread_mutex_lock error(%d): %s\n", err, strerror(err));
        return (-1);
    }

    if ( (mulwheeltimer.old_sigalarm = signal(SIGALRM, sigalarm_handler)) == SIG_ERR ) {
        pthread_mutex_destroy(&mulwheeltimer.lock);
        return (-1);
    }

    mulwheeltimer.new_sigalarm = sigalarm_handler;

    /**
     * 设置时间间隔为 it_interval 的定时器。
     * it_interval 应该设置成为后期添加的定时器的最小时间间隔。默认为秒:
     *   MUL_WHEEL_TIMER_TIMEUNIT_SEC
     */
    if (timeunit_sec == MUL_WHEEL_TIMER_TIMEUNIT_DEFAULT) {
        mulwheeltimer.value.it_interval.tv_sec = MUL_WHEEL_TIMER_TIMEUNIT_SEC;
        mulwheeltimer.value.it_interval.tv_usec = 0;
    } else {
        mulwheeltimer.value.it_interval.tv_sec = timeunit_sec;
        mulwheeltimer.value.it_interval.tv_usec = 0;
    }

    /** 设置时间间隔,以秒为单位:本程序不提供秒以下的定时器,如果需要请用户自行扩充!*/
    mulwheeltimer.timeunit = mulwheeltimer.value.it_interval.tv_sec;

    /** 设置到期时间为 it_value 的定时器,一旦时间达到 it_value,内核使用 it_interval 重启定时器 */
    if (timedelay_sec <= 0) {
        mulwheeltimer.value.it_value.tv_sec = mulwheeltimer.value.it_interval.tv_sec;
        mulwheeltimer.value.it_value.tv_usec = 0;
    } else {
        mulwheeltimer.value.it_value.tv_sec = timedelay_sec;
        mulwheeltimer.value.it_value.tv_usec = 0;
    }

    if (start) {
        err = setitimer(ITIMER_REAL, &mulwheeltimer.value, &mulwheeltimer.ovalue);
        if (! err) {
            /** 定时器成功创建并启动 */
            mulwheeltimer.status = 1;
            pthread_mutex_unlock(&mulwheeltimer.lock);
            printf("[mwt] create success.\n");
            return 0;
        } else {
            /** 定时器创建但启动失败 */
            mulwheeltimer.status = 0;
            pthread_mutex_destroy(&mulwheeltimer.lock);
            printf("[mwt] create failed.\n");
            return (-1);
        }
    } else {
        /** 定时器成功创建, 但不要求启动 */
        mulwheeltimer.status = 0;
        pthread_mutex_unlock(&mulwheeltimer.lock);
        printf("[mwt] create success with no start.\n");
        return 0;
    }
}


/**
 * mul_wheel_timer_start
 *   启动定时器
 *
 * returns:
 *    0: success  成功启动
 *    1: sfalse   已经启动
 *   -1: error    启动失败
 */
__attribute__((used))
static int mul_wheel_timer_start (void)
{
    int err;

    err = pthread_mutex_trylock(&mulwheeltimer.lock);
    if (err) {
        /** 多线程锁定失败 */
        printf("[mwt] pthread_mutex_trylock error(%d): %s\n", err, strerror(err));
        return (-1);
    }

    if (mulwheeltimer.status == 1) {
        /** 已经启动 */
        pthread_mutex_unlock(&mulwheeltimer.lock);
        printf("[mwt] already start.\n");
        return 1;
    }

    err = setitimer(ITIMER_REAL, &mulwheeltimer.value, &mulwheeltimer.ovalue);
    if (! err) {
        /** 定时器成功启动 */
        mulwheeltimer.status = 1;
        pthread_mutex_unlock(&mulwheeltimer.lock);
        printf("[mwt] start success.\n");
        return 0;
    } else {
        /** 定时器启动失败 */
        mulwheeltimer.status = 0;
        pthread_mutex_unlock(&mulwheeltimer.lock);
        printf("[mwt] start error.\n");
        return (-1);
    }
}


/**
 * mul_wheel_timer_destroy
 *
 * returns:
 *    0: success
 *   -1: failed.
 *      use strerror(errno) for error message.
 */
__attribute__((used))
static int mul_wheel_timer_destroy (void)
{
    int err;

    err = pthread_mutex_lock(&mulwheeltimer.lock);
    if (err) {
        printf("[mwt] pthread_mutex_lock error(%d): %s\n", err, strerror(err));
        return (-1);
    }

    if ((signal(SIGALRM, mulwheeltimer.new_sigalarm)) == SIG_ERR) {
        pthread_mutex_unlock(&mulwheeltimer.lock);
        printf("[mwt] destroy failed. signal error.\n");
        return (-1);
    }

    /** 恢复进程原有的定时器 */
    err = setitimer(ITIMER_REAL, &mulwheeltimer.ovalue, &mulwheeltimer.value);
    if (err < 0) {
        pthread_mutex_unlock(&mulwheeltimer.lock);
        printf("[mwt] destroy failed. setitimer error(%d): %s.\n", errno, strerror(errno));
        return (-1);
    }

    /** 清空定时器链表 */
#if MUL_WHEEL_TIMER_HAS_DLIST == 1
    do {
        struct list_head *list, *node;

        list_for_each_safe(list, node, &mulwheeltimer.dlist) {
            struct mul_timer_event_t * event = list_entry(list, struct mul_timer_event_t, i_list);

            hlist_del(&event->i_hash);
            list_del(&event->i_list);

            free_timer_event(event);
        }
    } while(0);
#else
    do {
        int hash;
        struct hlist_node *hp, *hn;

        for (hash = 0; hash <= MUL_WHEEL_TIMER_HASHLEN_MAX; hash++) {
            hlist_for_each_safe(hp, hn, &mulwheeltimer.hlist[hash]) {
                struct mul_timer_event_t * event = hlist_entry(hp, struct mul_timer_event_t, i_hash);

                hlist_del(&event->i_hash);

                free_timer_event(event);
            }
        }
    } while(0);
#endif

    pthread_mutex_destroy(&mulwheeltimer.lock);

    bzero(&mulwheeltimer, sizeof(struct mul_wheel_timer_t));

    printf("[mwt] destroy success.\n");
    return(0);
}


/**
 * mul_wheel_timer_set_event
 *   设置 event timer
 *
 * params:
 *   timedelay_sec - 指定首次激发的时间:当前定时器首次启动之后多少秒时间激发 event。
 *       0 : 立即激发
 *     > 0 : 延迟时间(秒)
 *
 *   timeinterval_sec - 首次激发 event 之后间隔多少秒激发。
 *       0 : 不激发
 *     > 0 : 间隔多少秒时间激发
 *
 * returns:
 *    > 0: mul_eventid_t, success
 *    < 0: failed
 */
__attribute__((used))
static mul_eventid_t mul_wheel_timer_set_event (unsigned int timedelay_sec, unsigned int timeinterval_sec,
    int (*on_event_cb)(mul_event_handle eventhdl, void *eventarg), void *eventarg)
{
    int err, hash;
    int64_t on_counter;
    mul_timer_event_t *new_event;

    if (timedelay_sec == -1 || timeinterval_sec == -1) {
        /** 无效的定时器 */
        return (-2);
    }

    err = pthread_mutex_trylock(&mulwheeltimer.lock);
    if (err) {
        /** 多线程锁定失败 */
        printf("[mwt] pthread_mutex_trylock error(%d): %s\n", err, strerror(err));
        return (-1);
    }

    /** 当 mulwheeltimer.counter == on_counter 时激发
     * 因此设置以 on_counter 为 hash 键保存 event
     */
    on_counter = timer_on_counter_hash(&mulwheeltimer, timedelay_sec, &hash);

    new_event = (mul_timer_event_t *) malloc(sizeof(mul_timer_event_t));
    if (! new_event) {
        /** out of memory */
        pthread_mutex_unlock(&mulwheeltimer.lock);
        return (-4);
    }

    bzero(new_event, sizeof(mul_timer_event_t));

    new_event->eventid = mulwheeltimer.eventid++;

    new_event->on_counter = on_counter;

    /** 当前时间 */
    new_event->value.it_value.tv_sec = timedelay_sec;

    /** 下次时间 */
    new_event->value.it_interval.tv_sec = timeinterval_sec;

    new_event->hash = hash;

    /** 设置回调参数和函数,回调函数由用户自己实现 */
    new_event->eventarg = eventarg;
    new_event->timer_event_cb = on_event_cb;

    printf("\033[31m+create event_%lld. (%d:%d)\033[0m\n", (long long) new_event->eventid,
        (int) new_event->value.it_value.tv_sec, (int) new_event->value.it_interval.tv_sec);

#if MUL_WHEEL_TIMER_HAS_DLIST == 1
    /** 串入长串 */
    list_add(&new_event->i_list, &mulwheeltimer.dlist);
#endif

    /** 串入HASH短串 */
    hlist_add_head(&new_event->i_hash, &mulwheeltimer.hlist[hash]);

    /** 设置引用计数为 1 */
    new_event->refc = 1;

    // 演示如何删除自身:
    ////hlist_del(&new_event->i_hash);
    ////list_del(&new_event->i_list);
    ////free_timer_event(new_event);

    pthread_mutex_unlock(&mulwheeltimer.lock);

    return new_event->eventid;
}


/**
 * mul_wheel_timer_remove_event
 *   从多定时器中删除事件。该调用仅仅标记事件要删除。真正删除的行为由系统决定。
 *
 * returns:
 *    0: success
 *   -1: failed.
 */
__attribute__((used))
static int mul_wheel_timer_remove_event (mul_event_handle eventhdl)
{
    mul_timer_event_t * event = mul_handle_cast_event(eventhdl);

    printf("remove event-%lld\n", (long long) event->eventid);

    /** 设置引用计数为 0,当有事件触发时自动删除 */
    __sync_lock_release(&event->refc);

    return 0;
}


/**
 * mul_wheel_timer_fire_event
 *   根据当前激发的 counter 查找 event
 *
 * params:
 *   on_counter - 当前激发的计数器
 *
 * returns:
 */
__attribute__((used))
static mul_timer_event_t * mul_wheel_timer_fire_event (int64_t fire_counter)
{
    struct hlist_node *hp;
    struct hlist_node *hn;

    int hash = (int) (fire_counter & MUL_WHEEL_TIMER_HASHLEN_MAX);

    hlist_for_each_safe(hp, hn, &mulwheeltimer.hlist[hash]) {
        struct mul_timer_event_t * event = hlist_entry(hp, struct mul_timer_event_t, i_hash);

        if (event->on_counter == fire_counter) {
            /** 首先从链表中删除自己 */
            hlist_del(&event->i_hash);

        #if MUL_WHEEL_TIMER_HAS_DLIST == 1
            list_del(&event->i_list);
        #endif

            if (__sync_lock_test_and_set(&event->refc, 1) == 0) {
                /** 要求删除事件 */
                free_timer_event(event);
            } else {
                /** 激发事件回调函数 */
                event->timer_event_cb(&event->eventid, event->eventarg);

                if (event->value.it_interval.tv_sec == 0) {
                    /* 只使用一次, 下次不再激发,删除事件 */
                    free_timer_event(event);
                } else {
                    event->on_counter = timer_on_counter_hash(&mulwheeltimer, event->value.it_interval.tv_sec, &event->hash);

                #if MUL_WHEEL_TIMER_HAS_DLIST == 1
                    /** 串入长串 */
                    list_add(&event->i_list, &mulwheeltimer.dlist);
                #endif
                    /** 串入HASH短串 */
                    hlist_add_head(&event->i_hash, &mulwheeltimer.hlist[event->hash]);
                }
            }
        }
    }

    return 0;
}


__attribute__((used))
static void sigalarm_handler(int signo)
{
    int err;
    int64_t on_counter;

    err = pthread_mutex_trylock(&mulwheeltimer.lock);
    if (err) {
        /** 多线程锁定失败 */
        printf("[mwt]\033[33m lock error: %llu\033[0m\n", (unsigned long long) mulwheeltimer.counter);
        return;
    }

    /** 当前激发的计数器 */
    on_counter = mulwheeltimer.counter++;

    /**
     * 激发事件:此事件在锁定状态下调用用户提供的回调函数:
     *   on_timer_event
     *
     * !! 因此不可以在on_timer_event中执行长时间的操作 !!
     */
    mul_wheel_timer_fire_event(on_counter);

    pthread_mutex_unlock(&mulwheeltimer.lock);

    printf(" * alarm: %llu\n", (unsigned long long) on_counter);
}


#if defined(__cplusplus)
}
#endif

#endif /* MUL_WHEEL_TIMER_H_INCLUDED */

双链表的C代码:

/**
 * dhlist.h
 *  - deque list and hash list from Linux Kernel
 *
 * from Linux Kernel
 * for Windows and Linux
 *
 * modified by cheungmine
 * 2013-4, 2018-02-03
 */
#ifndef _DH_LIST_H
#define _DH_LIST_H

#if defined(__cplusplus)
extern "C" {
#endif

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>


/**
 * BKDR Hash Function
 *   http://www.cnblogs.com/-clq/archive/2012/05/31/2528153.html
 */
static inline unsigned int BKDRHash (char *str)
{
    /* seed: 31 131 1313 13131 131313 etc.. */
    unsigned int seed = 131;
    unsigned int hash = 0;

    while (*str) {
        hash = hash * seed + (*str++);
    }

    return (hash & 0x7FFFFFFF);
}


static inline unsigned int BKDRHash2 (char *str, int hashlen)
{
    /* seed: 31 131 1313 13131 131313 etc.. */
    unsigned int seed = 131;
    unsigned int hash = 0;

    while (*str) {
        hash = hash * seed + (*str++);
    }

    return ((hash & 0x7FFFFFFF) & hashlen);
}


#ifdef CONFIG_ILLEGAL_POINTER_VALUE
#  define POISON_POINTER_DELTA  _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
#else
#  define POISON_POINTER_DELTA  0
#endif

/**
 * These are non-NULL pointers that will result in page faults
 * under normal circumstances, used to verify that nobody uses
 * non-initialized list entries.
 */
#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)


#ifdef typeof

static inline void prefetch(const void *x) {;}
static inline void prefetchw(const void *x) {;}

/**
 * filename: linux-2.6.7/include/linux/stddef.h
 */
#define OFFSET_OF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define CONTAINER_OF(ptr, type, member) ( { \
    const typeof( ((type *)0)->member ) *__mptr = (ptr); \
    (type *)( (char *)__mptr - OFFSET_OF(type,member) ); } )

#else

static inline int prefetch(const void *x) {;return 1;}
static inline int prefetchw(const void *x) {;return 1;}

#define OFFSET_OF(type, field)    ((unsigned int) (uintptr_t) (void*) &((type *)0)->field)

#define CONTAINER_OF(address, type, field) \
    ((type *)((char *)(address) - OFFSET_OF(type, field)))

#endif  /* typeof */

struct list_head
{
    struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

#define INIT_LIST_HEAD(ptr) do { \
        (ptr)->next = (ptr); (ptr)->prev = (ptr); \
    } while (0)

/*
 * Insert a new entry between two known consecutive entries.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_add(struct list_head *_new,
                              struct list_head *prev,
                              struct list_head *next)
{
    next->prev = _new;
    _new->next = next;
    _new->prev = prev;
    prev->next = _new;
}

/**
 * list_add - add a new entry
 * @new: new entry to be added
 * @head: list head to add it after
 *
 * Insert a new entry after the specified head.
 * This is good for implementing stacks.
 */
static inline void list_add(struct list_head *_new, struct list_head *head)
{
    __list_add(_new, head, head->next);
}

/**
 * list_add_tail - add a new entry
 * @new: new entry to be added
 * @head: list head to add it before
 *
 * Insert a new entry before the specified head.
 * This is useful for implementing queues.
 */
static inline void list_add_tail(struct list_head *_new, struct list_head *head)
{
    __list_add(_new, head->prev, head);
}

static inline void __list_del(struct list_head * prev, struct list_head * next)
{
    next->prev = prev;
    prev->next = next;
}

static inline void list_del(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    entry->next = (struct list_head*) LIST_POISON1;
    entry->prev = (struct list_head*) LIST_POISON2;
}

static inline void list_del_init(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    INIT_LIST_HEAD(entry);
}

static inline void list_move(struct list_head *list, struct list_head *head)
{
    __list_del(list->prev, list->next);
    list_add(list, head);
}

static inline void list_move_tail(struct list_head *list, struct list_head *head)
{
    __list_del(list->prev, list->next);
    list_add_tail(list, head);
}

static inline int list_empty(const struct list_head *head)
{
    return head->next == head;
}

static inline int list_empty_careful(const struct list_head *head)
{
    struct list_head *next = head->next;
    return (next == head) && (next == head->prev);
}

static inline void __list_splice(struct list_head *list, struct list_head *head)
{
    struct list_head *first = list->next;
    struct list_head *last = list->prev;
    struct list_head *at = head->next;

    first->prev = head;
    head->next = first;

    last->next = at;
    at->prev = last;
}

/**
 * list_splice - join two lists
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice(struct list_head *list, struct list_head *head)
{
    if (!list_empty(list)) {
        __list_splice(list, head);
    }
}

/**
 * list_splice_init - join two lists and reinitialise the emptied list.
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 *
 * The list at @list is reinitialised
 */
static inline void list_splice_init(struct list_head *list, struct list_head *head)
{
    if (!list_empty(list)) {
        __list_splice(list, head);
        INIT_LIST_HEAD(list);
    }
}

#define list_entry(ptr, type, member) \
    CONTAINER_OF(ptr, type, member)

#define list_for_each(pos, head) \
    for (pos = (head)->next; prefetch(pos->next), pos != (head); \
         pos = pos->next)

#define __list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

#define list_for_each_prev(pos, head) \
    for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
         pos = pos->prev)

#define list_for_each_safe(pos, n, head) \
    for (pos = (head)->next, n = pos->next; pos != (head); \
         pos = n, n = pos->next)

#ifdef typeof

#define list_for_each_entry(pos, head, member) \
    for (pos = list_entry((head)->next, typeof(*pos), member); \
         prefetch(pos->member.next), &pos->member != (head); \
         pos = list_entry(pos->member.next, typeof(*pos), member))

#define list_for_each_entry_reverse(pos, head, member) \
    for (pos = list_entry((head)->prev, typeof(*pos), member); \
         prefetch(pos->member.prev), &pos->member != (head); \
         pos = list_entry(pos->member.prev, typeof(*pos), member))

#define list_prepare_entry(pos, head, member) \
        ((pos) ? : list_entry(head, typeof(*pos), member))

#define list_for_each_entry_continue(pos, head, member) \
    for (pos = list_entry(pos->member.next, typeof(*pos), member); \
         prefetch(pos->member.next), &pos->member != (head); \
         pos = list_entry(pos->member.next, typeof(*pos), member))

#define list_for_each_entry_safe(pos, n, head, member) \
    for (pos = list_entry((head)->next, typeof(*pos), member), \
           n = list_entry(pos->member.next, typeof(*pos), member); \
         &pos->member != (head); \
         pos = n, n = list_entry(n->member.next, typeof(*n), member))
#else

#define list_for_each_entry(pos, typeof_pos, head, member) \
    for (pos = list_entry((head)->next, typeof_pos, member); \
         prefetch(pos->member.next), &pos->member != (head); \
         pos = list_entry(pos->member.next, typeof_pos, member))

#define list_for_each_entry_reverse(pos, typeof_pos, head, member) \
    for (pos = list_entry((head)->prev, typeof_pos, member); \
         prefetch(pos->member.prev), &pos->member != (head); \
         pos = list_entry(pos->member.prev, typeof_pos, member))

#define list_prepare_entry(pos, typeof_pos, head, member) \
        ((pos) ? : list_entry(head, typeof_pos, member))

#define list_for_each_entry_continue(pos, typeof_pos, head, member) \
    for (pos = list_entry(pos->member.next, typeof_pos, member); \
         prefetch(pos->member.next), &pos->member != (head); \
         pos = list_entry(pos->member.next, typeof_pos, member))

#define list_for_each_entry_safe(pos, typeof_pos, n, typeof_n, head, member) \
    for (pos = list_entry((head)->next, typeof_pos, member), \
           n = list_entry(pos->member.next, typeof_pos, member); \
         &pos->member != (head); \
         pos = n, n = list_entry(n->member.next, typeof_n, member))

#endif  /* typeof */

/**
 * HASH LIST
 */
struct hlist_head {
    struct hlist_node *first;
};

struct hlist_node {
    struct hlist_node *next, **pprev;
};

#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)

static inline int hlist_unhashed(const struct hlist_node *h)
{
    return !h->pprev;
}

static inline int hlist_empty(const struct hlist_head *h)
{
    return !h->first;
}

static inline void __hlist_del(struct hlist_node *n)
{
    struct hlist_node *next = n->next;
    struct hlist_node **pprev = n->pprev;
    *pprev = next;
    if (next) {
        next->pprev = pprev;
    }
}

static inline void hlist_del(struct hlist_node *n)
{
    __hlist_del(n);
    n->next = (struct hlist_node*) LIST_POISON1;
    n->pprev = (struct hlist_node**) LIST_POISON2;
}

static inline void hlist_del_init(struct hlist_node *n)
{
    if (n->pprev) {
        __hlist_del(n);
        INIT_HLIST_NODE(n);
    }
}

static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
    struct hlist_node *first = h->first;
    n->next = first;
    if (first) {
        first->pprev = &n->next;
    }
    h->first = n;
    n->pprev = &h->first;
}

/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n, struct hlist_node *next)
{
    n->pprev = next->pprev;
    n->next = next;
    next->pprev = &n->next;
    *(n->pprev) = n;
}

static inline void hlist_add_after(struct hlist_node *n, struct hlist_node *next)
{
    next->next = n->next;
    n->next = next;
    next->pprev = &n->next;

    if (next->next) {
        next->next->pprev  = &next->next;
    }
}

#define hlist_entry(ptr, type, member) \
    CONTAINER_OF(ptr, type, member)

#ifdef typeof

#define hlist_for_each(pos, head) \
    for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
         pos = pos->next)

#define hlist_for_each_safe(pos, n, head) \
    for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
         pos = n)

#define hlist_for_each_entry(tpos, pos, head, member) \
    for (pos = (head)->first; \
         pos && ({ prefetch(pos->next); 1;}) && \
            ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = pos->next)

#define hlist_for_each_entry_continue(tpos, pos, member) \
    for (pos = (pos)->next; \
         pos && ({ prefetch(pos->next); 1;}) && \
            ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = pos->next)

#define hlist_for_each_entry_from(tpos, pos, member) \
    for (; pos && ({ prefetch(pos->next); 1;}) && \
            ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = pos->next)

#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
    for (pos = (head)->first; \
         pos && ({ n = pos->next; 1; }) && \
            ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = n)
#else

#define hlist_for_each(pos, head) \
    for (pos = (head)->first; pos && prefetch(pos->next); pos = pos->next)

/** warning: operation on ‘hn’ may be undefined [-Wsequence-point]
#define hlist_for_each_safe(pos, n, head) \
    for (pos = (head)->first; pos && ((n=pos->next) == n); pos = n)
*/
#define hlist_for_each_safe(pos, n, head) \
    for (pos = (head)->first; pos && ({ n = pos->next; 1; }); pos = n)

#define hlist_for_each_entry(tpos, typeof_tpos, pos, head, member) \
    for (pos = (head)->first; \
         pos && prefetch(pos->next) && \
           ((tpos = hlist_entry(pos, typeof_tpos, member)) == tpos); \
         pos = pos->next)

#define hlist_for_each_entry_continue(tpos, typeof_tpos, pos, member) \
    for (pos = (pos)->next; \
         pos && prefetch(pos->next) && \
            ((tpos = hlist_entry(pos, typeof_tpos, member)) == tpos); \
         pos = pos->next)

#define hlist_for_each_entry_from(tpos, typeof_tpos, pos, member) \
    for (; pos && prefetch(pos->next) && \
            ((tpos = hlist_entry(pos, typeof_tpos, member)) == tpos); \
         pos = pos->next)

#define hlist_for_each_entry_safe(tpos, typeof_tpos, pos, n, head, member) \
    for (pos = (head)->first; \
         pos && ((n = pos->next) == n) && \
            ((tpos = hlist_entry(pos, typeof_tpos, member)) == tpos); \
         pos = n)

#endif /* typeof */

#if defined(__cplusplus)
}
#endif

#endif /* _DH_LIST_H */

如何使用例子

#include "mul_wheel_timer.h"


int on_timer_event (mul_event_handle eventhdl, void *eventarg)
{
    printf(" ==> on_timer_event_%lld\n", (long long) * eventhdl);

    //mul_wheel_timer_remove_event(eventhdl);

    return 0;
}


int main (int argc, char *argv[])
{
    int err;

    printf("start ...\n");

    err = mul_wheel_timer_create(MUL_WHEEL_TIMER_TIMEUNIT_DEFAULT, 0, 0);
    assert(! err);

    // 添加首次20秒激发,以后间隔3秒激发的定时器
    mul_wheel_timer_set_event(20, 3, on_timer_event, 0);

    // 添加首次30秒激发,以后间隔5秒激发的定时器
    mul_wheel_timer_set_event(30, 5, on_timer_event, 0);

    // 添加一次性定时器,仅在第10秒激发一次
    mul_wheel_timer_set_event(10, 0, on_timer_event, 0);

    mul_wheel_timer_start();

    while (1)
    {
        pause();
    }

    err = mul_wheel_timer_destroy();
    assert(! err);

    printf("exit.\n");

    return 0;
}

猜你喜欢

转载自blog.csdn.net/cheungmine/article/details/79249987
今日推荐