259 lines
5.7 KiB
C
259 lines
5.7 KiB
C
/*
|
|
* PVVMUD a 3D MUD
|
|
* Copyright (C) 1998-1999 Programvareverkstedet (pvv@pvv.org)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
#include "pvvmud.H"
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
#include <sys/types.h>
|
|
#include <iostream.h>
|
|
#include "timekeeper.H"
|
|
#include "exception.H"
|
|
|
|
#define mrealloc(ptr, size) ((ptr) ? realloc(ptr, size) : malloc(size))
|
|
#define nextsize(size) (((size)==0) ? 20 : ((size)*2))
|
|
|
|
// Infinite time not defined on all os
|
|
#ifndef INFTIM
|
|
#define INFTIM -1
|
|
#endif
|
|
|
|
//#define DEBUG_TIMEKEEPER
|
|
|
|
int CTimeKeeperItem::timeKeeperFD(int event){
|
|
return FALSE;
|
|
}
|
|
|
|
int CTimeKeeperItem::timeKeeperSetEvents(int event){
|
|
if (m_timeKeeper != NULL){
|
|
m_timeKeeper->setEvents(this,event);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int CTimeKeeperItem::timeKeeperHB(){
|
|
return FALSE;
|
|
}
|
|
|
|
CTimeKeeper::CTimeKeeper() {
|
|
|
|
hbs=NULL;
|
|
num_hbs=0; size_hbs=0;
|
|
|
|
fds=NULL; timeKeeperFD=NULL;
|
|
num_fdns=0; size_fds=0;
|
|
|
|
mintimeout=INT_MAX;
|
|
num=0;
|
|
running=0;
|
|
setTime();
|
|
}
|
|
|
|
CTimeKeeper::~CTimeKeeper(){
|
|
}
|
|
|
|
void
|
|
CTimeKeeper::setTime() {
|
|
struct timezone tzp;
|
|
gettimeofday(&lasttime, &tzp);
|
|
}
|
|
|
|
int
|
|
CTimeKeeper::getTime() {
|
|
struct timezone tzp;
|
|
struct timeval tv;
|
|
gettimeofday(&tv, &tzp);
|
|
return ((tv.tv_sec-lasttime.tv_sec)*1000
|
|
+(tv.tv_usec-lasttime.tv_usec)/1000);
|
|
}
|
|
|
|
int
|
|
CTimeKeeper::addFd(int fd, CTimeKeeperItem * fn, short events) {
|
|
|
|
fn->timeKeeperSetTimeKeeper(this);
|
|
|
|
if (size_fds<=num_fdns) {
|
|
size_fds = nextsize(size_fds);
|
|
fds = (struct pollfd *)mrealloc(fds, size_fds*sizeof(struct pollfd));
|
|
timeKeeperFD = (CTimeKeeperItem **)mrealloc(timeKeeperFD,size_fds*sizeof(CTimeKeeperItem*));
|
|
|
|
if ((fds == NULL) | (timeKeeperFD == NULL)){
|
|
throw new CException("Out of memory exception");
|
|
}
|
|
|
|
}
|
|
|
|
fds[num_fdns].fd = fd;
|
|
fds[num_fdns].events = events;
|
|
fds[num_fdns].revents = 0;
|
|
timeKeeperFD[num_fdns] = fn;
|
|
num_fdns++;
|
|
return 0;
|
|
}
|
|
|
|
|
|
#define MYmemmove(a,b,c) cdebug << "Memmove(Dest= " << a << ",Src= " << b << ",Length= " << c << ");\n"; memmove(a,b,c)
|
|
|
|
int
|
|
CTimeKeeper::rmFd(int fd) {
|
|
int i = num_fdns-1;
|
|
while (i >= 0){
|
|
// for (i=0; i<num_fdns; i++) {
|
|
if (fds[i].fd == fd) {
|
|
#ifdef DEBUG_TIMEKEEPER
|
|
cdebug << "CTimeKeeper::rmFD ( " << fd << " ) at pos : " << i << "\n";
|
|
#endif
|
|
memmove(&fds[i], &fds[i+1], (DWORD)&fds[num_fdns]-(DWORD)&fds[i+1]);
|
|
memmove(&timeKeeperFD[i], &timeKeeperFD[i+1], (DWORD)&timeKeeperFD[num_fdns]-(DWORD)&timeKeeperFD[i+1]);
|
|
num_fdns--;
|
|
return 1;
|
|
}
|
|
i--;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int CTimeKeeper::setEvents(CTimeKeeperItem * fn,short events){
|
|
int i;
|
|
for (i=0; i<num_fdns; i++) {
|
|
if (timeKeeperFD[i] == fn) {
|
|
fds[i].events = events;
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
CTimeKeeper::addHeartBeat(int timeout, CTimeKeeperItem * fn) {
|
|
int nsize, i;
|
|
void *nptr;
|
|
if (size_hbs<=num_hbs) {
|
|
nsize = nextsize(size_hbs);
|
|
nptr = mrealloc(hbs, nsize*sizeof(struct heartbeat));
|
|
if (!nptr) return 1;
|
|
size_hbs = nsize;
|
|
hbs = (struct heartbeat *)nptr;
|
|
}
|
|
|
|
/* round down to nearest 2^n */
|
|
for (i=0; timeout &= ~(1<<i) ; i++);
|
|
timeout = 1<<i;
|
|
|
|
hbs[num_hbs].timeout = timeout;
|
|
if (timeout < mintimeout) mintimeout=timeout;
|
|
hbs[num_hbs].fn = fn;
|
|
num_hbs++;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
CTimeKeeper::rmHeartBeat(CTimeKeeperItem * fn) {
|
|
int i, j;
|
|
for (i=0; i<num_hbs; i++) {
|
|
if (hbs[i].fn == fn) {
|
|
memmove(&hbs[i], &hbs[i+1], &hbs[num_hbs]-&hbs[i+1]);
|
|
num_hbs--;
|
|
mintimeout = INT_MAX;
|
|
for (j=0; j<num_hbs; j++) {
|
|
if (hbs[i].timeout < mintimeout)
|
|
mintimeout=hbs[i].timeout;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
CTimeKeeper::stopLoop() {
|
|
running=0;
|
|
}
|
|
|
|
|
|
void
|
|
CTimeKeeper::mainLoop() {
|
|
running=1;
|
|
while (running) {
|
|
|
|
poll( ((mintimeout == INT_MAX) ? INFTIM : mintimeout) );
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
CTimeKeeper::poll(int timeOut) {
|
|
int nready, i;
|
|
|
|
nready = ::poll(fds, num_fdns,timeOut);
|
|
// cdebug << "Poll : " << nready << "\n";
|
|
|
|
#ifdef DEBUG_TIMEKEEPER
|
|
if (nready > 0){
|
|
cdebug << "CTimeKeeper::poll(...)\n";
|
|
cdebug << " nready : " << nready << "\n";
|
|
i = num_fdns-1;
|
|
while (i >= 0){
|
|
cdebug << " fds[" << i << "].fd : " << fds[i].fd << "\n";
|
|
cdebug << " fds[" << i << "].events : " << fds[i].events << "\n";
|
|
cdebug << " fds[" << i << "].revents : " << fds[i].revents << "\n";
|
|
cdebug << " timeKeeperFD[" << i << "].getName() : "
|
|
<< timeKeeperFD[i]->getName() << "\n";
|
|
i--;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
// for (i=0; nready > 0 && i < num_fdns; i++) {
|
|
i = num_fdns-1; // New
|
|
while (i >= 0){ // New
|
|
if (fds[i].revents) {
|
|
// cdebug << "Event : " << fds[i].revents << "\n";
|
|
if (!timeKeeperFD[i]->timeKeeperFD(fds[i].revents)){
|
|
rmFd(fds[i].fd);
|
|
// i--;
|
|
} else {
|
|
fds[i].revents=0;
|
|
}
|
|
// nready--;
|
|
}
|
|
i--; // New
|
|
}
|
|
|
|
if ( getTime() >= mintimeout ) {
|
|
for (i=0; i < num_hbs; i++) {
|
|
if (!(num % (hbs[i].timeout/mintimeout))) {
|
|
if (!hbs[i].fn->timeKeeperHB()){
|
|
rmHeartBeat(hbs[i].fn);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
num++;
|
|
setTime();
|
|
}
|
|
}
|
|
|
|
|