⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timers.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ====================================================================  * The Kannel Software License, Version 1.0  *  * Copyright (c) 2001-2004 Kannel Group   * Copyright (c) 1998-2001 WapIT Ltd.    * All rights reserved.  *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  *  * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  *  * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in  *    the documentation and/or other materials provided with the  *    distribution.  *  * 3. The end-user documentation included with the redistribution,  *    if any, must include the following acknowledgment:  *       "This product includes software developed by the  *        Kannel Group (http://www.kannel.org/)."  *    Alternately, this acknowledgment may appear in the software itself,  *    if and wherever such third-party acknowledgments normally appear.  *  * 4. The names "Kannel" and "Kannel Group" must not be used to  *    endorse or promote products derived from this software without  *    prior written permission. For written permission, please   *    contact org@kannel.org.  *  * 5. Products derived from this software may not be called "Kannel",  *    nor may "Kannel" appear in their name, without prior written  *    permission of the Kannel Group.  *  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,   * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT   * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE   * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  * ====================================================================  *  * This software consists of voluntary contributions made by many  * individuals on behalf of the Kannel Group.  For more information on   * the Kannel Group, please see <http://www.kannel.org/>.  *  * Portions of this software are based upon software originally written at   * WapIT Ltd., Helsinki, Finland for the Kannel project.   */ /* * timers.c - timers and set of timers, mainly for WTP. * * See timers.h for a description of the interface. */#include <signal.h>#include "gwlib/gwlib.h"#include "wap_events.h"#include "timers.h"/* * Active timers are stored in a TimerHeap.  It is a partially ordered * array.  Each element i is the child of element i/2 (rounded down), * and a child never elapses before its parent.  The result is that * element 0, the top of the heap, is always the first timer to * elapse.  The heap is kept in this partial order by all operations on * it.  Maintaining a partial order is much cheaper than maintaining * a sorted list. * The array will be resized as needed.  The size field is the number * of elements for which space is reserved, and the len field is the * number of elements actually used.  The elements used will always be * at tab[0] through tab[len-1]. */struct TimerHeap{    Timer **tab;    long len;    long size;};typedef struct TimerHeap TimerHeap;struct Timerset{    /*     * This field is set to true when the timer thread should shut down.     */    volatile sig_atomic_t stopping;    /*     * The entire set is locked for any operation on it.  This is     * not as expensive as it sounds because usually each set is     * used by one caller thread and one (internal) timer thread,     * and the timer thread does not wake up very often.     */    Mutex *mutex;    /*     * Active timers are stored here in a partially ordered structure.     * See the definition of TimerHeap, above, for an explanation.     */    TimerHeap *heap;    /*     * The thread that watches the top of the heap, and processes     * timers that have elapsed.     */    long thread;};typedef struct Timerset Timerset;struct Timer{    /*     * An event is produced on the output list when the     * timer elapses.  The timer is not considered to have     * elapsed completely until that pointer has also been     * consumed from this list (by the caller, presumably).     * That is why the timer code sometimes goes back and     * removes a pointer from the output list.     */    List *output;    /*     * The timer is set to elapse at this time, expressed in     * Unix time format.  This field is set to -1 if the timer     * is not active (i.e. in the timer set's heap).     */    long elapses;    /*     * A duplicate of this event will be put on the output list     * when the timer elapses.  It can be NULL if the timer has     * not been started yet.     */    WAPEvent *event;    /*     * This field is normally NULL, but after the timer elapses     * it points to the event that was put on the output list.     * It is set back to NULL if the event was taken back from     * the list, or if it's confirmed that the event was consumed.     */    WAPEvent *elapsed_event;    /*     * Index in the timer set's heap.  This field is managed by     * the heap operations, and is used to make them faster.     * If this timer is not in the heap, this field is -1.     */    long index;};/* * Currently we have one timerset (and thus one heap and one thread) * for all timers.  This might change in the future in order to tune * performance.  In that case, it will be necessary to add a "set" * field to the Timer structure. */static Timerset *timers;/* * Used by timer functions to assert that the timer module has been * intialized. */static int initialized = 0;/* * Internal functions */static void abort_elapsed(Timer *timer);static TimerHeap *heap_create(void);static void heap_destroy(TimerHeap *heap);static void heap_delete(TimerHeap *heap, long index);static int heap_adjust(TimerHeap *heap, long index);static void heap_insert(TimerHeap *heap, Timer *timer);static void heap_swap(TimerHeap *heap, long index1, long index2);static void lock(Timerset *set);static void unlock(Timerset *set);static void watch_timers(void *arg);   /* The timer thread */static void elapse_timer(Timer *timer);void timers_init(void){    if (initialized == 0) {        timers = gw_malloc(sizeof(*timers));        timers->mutex = mutex_create();        timers->heap = heap_create();        timers->stopping = 0;        timers->thread = gwthread_create(watch_timers, timers);    }    initialized++;}void timers_shutdown(void){    if (initialized > 1) {        initialized--;        return;    }           /* Stop all timers. */    if (timers->heap->len > 0)        warning(0, "Timers shutting down with %ld active timers.",                timers->heap->len);    while (timers->heap->len > 0)        gwtimer_stop(timers->heap->tab[0]);    /* Kill timer thread */    timers->stopping = 1;    gwthread_wakeup(timers->thread);    gwthread_join(timers->thread);    initialized = 0;    /* Free resources */    heap_destroy(timers->heap);    mutex_destroy(timers->mutex);    gw_free(timers);}Timer *gwtimer_create(List *outputlist){    Timer *t;    gw_assert(initialized);    t = gw_malloc(sizeof(*t));    t->elapses = -1;    t->event = NULL;    t->elapsed_event = NULL;    t->index = -1;    t->output = outputlist;    list_add_producer(outputlist);    return t;}void gwtimer_destroy(Timer *timer){    gw_assert(initialized);    if (timer == NULL)        return;    gwtimer_stop(timer);    list_remove_producer(timer->output);    wap_event_destroy(timer->event);    gw_free(timer);}void gwtimer_start(Timer *timer, int interval, WAPEvent *event){    int wakeup = 0;    gw_assert(initialized);    gw_assert(timer != NULL);    gw_assert(event != NULL || timer->event != NULL);    lock(timers);    /* Convert to absolute time */    interval += time(NULL);    if (timer->elapses > 0) {        /* Resetting an existing timer.  Move it to its new         * position in the heap. */        if (interval < timer->elapses && timer->index == 0)            wakeup = 1;        timer->elapses = interval;        gw_assert(timers->heap->tab[timer->index] == timer);        wakeup |= heap_adjust(timers->heap, timer->index);    } else {        /* Setting a new timer, or resetting an elapsed one.         * First deal with a possible elapse event that may         * still be on the output list. */        abort_elapsed(timer);        /* Then activate the timer. */        timer->elapses = interval;        gw_assert(timer->index < 0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -