Personal tools
You are here: Home Projects C++ Cfront releases Release 3.0.3 source lib task_SPARC TESTS real_timer.C
Document Actions

real_timer.C

by Michael L Powell last modified 2007-01-26 03:22

Click here to get the file

Size 2.9 kB - File type text/plain

File contents

#include "real_timer.h"
#include <stdio.h>

#define STATIC

unsigned	alarm(unsigned);
long		time(long*);

// only one instance of this class
class Alarm_handler : public task {
	friend Real_timer;
	Real_timer*	chain;
	Interrupt_handler*	bell;
	void	add_timer(Real_timer*);
	void	remove_timer(Real_timer*);
public:
		Alarm_handler();
};

Alarm_handler	alarm_handler;

Alarm_handler::Alarm_handler()
: task("Alarm_handler"), chain(0)
{
	sleep();
	for(;;) {
		for (long now = time(0); chain && chain->time <= now;
				chain = (Real_timer*)chain->o_next)
			chain->resume();
		if (chain) {
			alarm(chain->time - now);
			wait(bell);
		} else {
			bell->forget(this_task());
			delete bell;
			sleep();
		}
	}
}
	
void
Alarm_handler::add_timer(Real_timer* r)
{
	register Real_timer * p;
	register Real_timer * pp;

	unsigned delay = r->time;
	register long tt = r->time = time(0) + delay;
	/* chain ordered by time */
	if (p = chain) {
		if (tt < p->time) {
			r->o_next = chain;
			chain = r;
			alarm(delay);
		} else {
			while (pp = (Real_timer*)p->o_next) {
				if (r->time < pp->time) {
					r->o_next = pp;
					break;
				} else p = pp;
			}
			p->o_next = r;
		}
	} else {
		chain = r;
		bell = new Interrupt_handler(SIGALRM);
		bell->remember(this);
		alarm(delay);
	}
}
	
void
Real_timer::insert(int d)
{
	switch (state) {
	case TERMINATED:
		task_error(E_RESTERM);
		break;
	case IDLE:
		break;
	case RUNNING:
		task_error(E_RESRUN);
	}

	if (d<=0) task_error(E_NEGTIME);	

	if (o_next) task_error(E_RESOBJ);

	state = RUNNING;
	alarm_handler.add_timer(this);
}

void
Alarm_handler::remove_timer(Real_timer* r)
// remove from chain and make IDLE
{
	register class Real_timer * p;
	register class Real_timer * pp;

	alarm(0);
	if (p = chain)
		if (p == r)
			if (chain = (Real_timer*)r->o_next) {
				int delay = chain->time - time(0);
				if (delay > 0) alarm(delay);
			} else {
				alarm(0);
				bell->forget(this);
				delete bell;
			}
		else
			for (; pp = (Real_timer*)p->o_next; p=pp)
				if (pp == r) {
					p->o_next = pp->o_next;
					break;
				}
	r->state = IDLE;
	r->o_next = 0;
}

void
Real_timer::remove()
// remove from chain and make IDLE
{
	alarm_handler.remove_timer(this);
}

void
Real_timer::reset(int d)
{
	remove();
	insert(d);
}

void
Real_timer::resume()  // time is up
{
fprintf(stderr, "Real_timer::resume()\n");
	state = TERMINATED;
	alert();
}

int
Real_timer::pending()  // do we wait for this timer?
{
	return state != TERMINATED;
}

void
Real_timer::print(int n, int baseClass)
{
	if (!baseClass)
		fprintf(stderr, "Real_timer %ld==now+%ld, state==%s\n", time,
			time - ::time(0),
			state==RUNNING ? "RUNNING" :
			  state==IDLE ? "IDLE" :
			  state==TERMINATED ? "TERMINATED" : "error");

	object::print(n, 1);
}

int
Real_timer::o_type()
{
	return REAL_TIMER;
}

Real_timer::Real_timer(int d)
: time(d), state(IDLE)
{
	insert(d);
}

Real_timer::~Real_timer()
{
	if (state != TERMINATED) task_error(E_TIMERDEL);
}
« April 2024 »
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: