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

📄 timer.c

📁 数据挖掘经典的hierarchial clustering algorithm
💻 C
字号:
/*
  ========================================================================
  DEVise Data Visualization Software
  (c) Copyright 1992-1996
  By the DEVise Development Group
  Madison, Wisconsin
  All Rights Reserved.
  ========================================================================

  Under no circumstances is this software to be copied, distributed,
  or altered in any way without prior permission from the DEVise
  Development Group.
*/

/*
  $Id: Timer.c,v 1.13 1996/10/01 14:00:28 wenger Exp $

  $Log: Timer.c,v $
  Revision 1.13  1996/10/01 14:00:28  wenger
  Removed extra path info from includes.

  Revision 1.12  1996/08/02 00:38:08  jussi
  Added variable _nexthop where the length of the next hop
  is stored.

  Revision 1.11  1996/08/01 23:56:14  jussi
  Interval timer is now set for just one interval/interrupt at a
  time. There were occasional problems (SIGALRM's not caught properly)
  with the old scheme.

  Revision 1.10  1996/07/12 18:45:08  jussi
  Added check for negative "next event" case.

  Revision 1.9  1996/07/12 18:13:31  jussi
  Rewrote Timer code to use fewer timer interrupts and also
  allow for timer events which should precede any events
  already in the queue.

  Revision 1.8  1996/07/01 19:17:37  jussi
  Minor fix in StartTimer().

  Revision 1.7  1996/06/24 19:33:58  jussi
  Fixed small bugs, removed unused code, and added some
  debugging statements.

  Revision 1.6  1996/06/23 20:46:29  jussi
  Cleaned up.

  Revision 1.5  1996/05/20 18:44:41  jussi
  Replaced PENTIUM flag with SOLARIS.

  Revision 1.4  1996/03/26 15:34:38  wenger
  Fixed various compile warnings and errors; added 'clean' and
  'mostlyclean' targets to makefiles; changed makefiles so that
  object lists are derived from source lists.

  Revision 1.3  1996/02/13 16:21:20  jussi
  Fixed for AIX.

  Revision 1.2  1995/09/05 21:13:08  jussi
  Added/updated CVS header.
*/

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

#include "machdep.h"
#include "Timer.h"

//#define DEBUG

struct TimerQueueEntry {
    TimerQueueEntry *next;
    long when;
    int arg;
    TimerCallback *callback;
};

Boolean Timer::_initialized = false;
Boolean Timer::_inHandler = false;
Boolean Timer::_timerRunning = false;
TimerQueueEntry *Timer::_head = 0;
TimerQueueEntry *Timer::_freeHead = 0;
long Timer::_now = 0;
long Timer::_nexthop = 0;

/***********************************************************
Alloc timer queue entry
***********************************************************/

TimerQueueEntry *Timer::AllocEntry()
{
    TimerQueueEntry *entry;
    if (!_freeHead)
        entry = new TimerQueueEntry;
    else {
        entry = _freeHead;
        _freeHead = entry->next;
    }
    return entry;
}

/**************************************************************
Free a timer queue entry
***************************************************************/

void Timer::FreeEntry(TimerQueueEntry *entry)
{
    entry->next = _freeHead;
    _freeHead = entry;
}

/*****************************************************************
Queue up a timer event
*******************************************************************/

void Timer::Queue(long ms, TimerCallback *callback, int arg, Boolean first)
{
    if (!_initialized)
        InitTimer();

    StopTimer();

#ifdef DEBUG
    printf("Queueing timer 0x%p, arg %d at %ld, %s\n", callback, arg,
           _now + ms, (first ? "first" : "sorted"));
#endif

    TimerQueueEntry *entry = AllocEntry();
    entry->when = _now + ms;
    entry->callback = callback;
    entry->arg = arg;

    if (first) {
        /* place event first in queue */
        entry->next = _head;
        _head = entry;
    } else {
        /* queue event in ascending time order */
        TimerQueueEntry *next = _head;
        TimerQueueEntry *prev = 0;
        while (next && entry->when > next->when) {
            prev = next;
            next = next->next;
        }
        if (!prev)
            _head = entry;
        else
            prev->next = entry;
        entry->next = next;
    }

    StartTimer();
}

/*****************************************************************
Cancel a timer event
*******************************************************************/

void Timer::Cancel(TimerCallback *callback, int arg)
{
#ifdef DEBUG
    printf("Canceling timer 0x%p, arg %d\n", callback, arg);
#endif

    if (!_initialized)
        return;

    StopTimer();

    TimerQueueEntry *entry = _head;
    TimerQueueEntry *prev = 0;
    while (entry) {
        if (entry->callback == callback && entry->arg == arg) {
            if (!prev)
                _head = entry->next;
            else
                prev->next = entry->next;
            FreeEntry(entry);
#ifdef DEBUG
            printf("Timer canceled\n");
#endif
            break;
        }
        entry = entry->next;
    }

    StartTimer();
}

/********************************************************************
Handler of timer interrupt
*********************************************************************/

void Timer::TimerHandler(int arg)
{
    StopTimer();

    _inHandler = true;

    TimerQueueEntry *entry;
    while (_head && _head->when <= _now) {
        entry = _head;
        _head = _head->next;
#ifdef DEBUG
        printf("Waking up timer 0x%p, arg %d at %ld\n",
               entry->callback, entry->arg, entry->when);
#endif
        entry->callback->TimerWake(entry->arg);
        FreeEntry(entry);
    }

#ifdef DEBUG
    printf("Done with TimerHandler\n");
#endif

    _inHandler = false;

    (void)signal(SIGALRM, TimerHandler);

    StartTimer();
}

/************************************************************************
Initialize the timer
************************************************************************/

void Timer::InitTimer()
{
    if (_initialized)
        return;

    _now = 0;

    (void)signal(SIGALRM, TimerHandler);

    _inHandler = false;
    _timerRunning = false;

    _initialized = true;
}

/***********************************************************************
Stop the timer
************************************************************************/

void Timer::StopTimer()
{
    if (_inHandler || !_timerRunning)
        return;

    _timerRunning = false;

    struct itimerval timerVal;
    struct itimerval oldTimerVal;
    timerVal.it_value.tv_sec = 0;
    timerVal.it_value.tv_usec = 0;
    timerVal.it_interval.tv_sec = 0;
    timerVal.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &timerVal, &oldTimerVal);

    long left = oldTimerVal.it_value.tv_sec * 1000
                + oldTimerVal.it_value.tv_usec / 1000;

    if (left < _nexthop)
        _now += _nexthop - left;
    else
        _now += _nexthop;

#ifdef DEBUG
    printf("Timer now at %ld\n", _now);
#endif
}

/***********************************************************************
Restart the timer
*************************************************************************/

void Timer::StartTimer()
{
    if (_inHandler)
        return;

    if (!_head) {
#ifdef DEBUG
        printf("No timer event to schedule\n");
#endif
        return;
    }

    _timerRunning = true;

    _nexthop = _head->when - _now;

#ifdef DEBUG
    printf("Next timer event is after %ld ms\n", _nexthop);
#endif

    if (_nexthop < 1) {
        /* cannot set to zero, as the timer would be canceled */
        _nexthop = 1;
    }

    /* Set timer */
    struct itimerval timerVal;
    timerVal.it_interval.tv_sec = 0;
    timerVal.it_interval.tv_usec = 0;
    timerVal.it_value.tv_sec = _nexthop / 1000;
    timerVal.it_value.tv_usec = (_nexthop % 1000) * 1000;
    setitimer(ITIMER_REAL, &timerVal, 0);
}

⌨️ 快捷键说明

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