diff options
| author | Sam Varshavchik | 2013-08-19 16:39:41 -0400 | 
|---|---|---|
| committer | Sam Varshavchik | 2013-08-25 14:43:51 -0400 | 
| commit | 9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch) | |
| tree | 7a81a04cb51efb078ee350859a64be2ebc6b8813 /maildrop/alarm.C | |
| parent | a9520698b770168d1f33d6301463bb70a19655ec (diff) | |
| download | courier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2 | |
Initial checkin
Imported from subversion report, converted to git. Updated all paths in
scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'maildrop/alarm.C')
| -rw-r--r-- | maildrop/alarm.C | 124 | 
1 files changed, 124 insertions, 0 deletions
| diff --git a/maildrop/alarm.C b/maildrop/alarm.C new file mode 100644 index 0000000..f65005a --- /dev/null +++ b/maildrop/alarm.C @@ -0,0 +1,124 @@ +#include	"config.h" +#include	<iostream> + + +#if HAVE_UNISTD_H +#include	<unistd.h> +#else +extern "C" long alarm(long); +#endif + +#include	<signal.h> +#include	"alarm.h" + +Alarm *Alarm::first=0; +Alarm *Alarm::last=0; + +Alarm::~Alarm() +{ +	Cancel(); +} + +void Alarm::Unlink() +{ +	set_interval=0; +	if (prev)	prev->next=next; +	else		first=next; +	if (next)	next->prev=prev; +	else		last=prev; +} + +void Alarm::cancel_sig(unsigned seconds_left) +{ +Alarm	*p; +Alarm	*alarm_chain=0; + +	while ((p=first) != 0 && p->set_interval <= seconds_left) +			// Marginal case +	{ +		p->Unlink(); +		p->next=alarm_chain; +		alarm_chain=p; +	} + +	for (p=first; p; p=p->next) +		p->set_interval -= seconds_left; + +	while ((p=alarm_chain) != 0) +	{ +		alarm_chain=p->next; +		p->handler(); +	} +} + +void Alarm::set_sig() +{ +	if (!first)	return; +	signal(SIGALRM, &Alarm::alarm_func); +	alarm(first->set_interval); +} + +RETSIGTYPE Alarm::alarm_func(int) +{ +	if (first)	cancel_sig(first->set_interval); +	set_sig(); + +#if RETSIGTYPE != void +	return (0); +#endif +} + +unsigned Alarm::sig_left() +{ +	if (!first)	return (0); + +unsigned n=alarm(0); + +	return (n ? n <= first->set_interval ? first->set_interval - n:0:0); +} + +void Alarm::Set(unsigned nseconds) +{ +	Cancel();		// Just in case +	if (nseconds == 0) +	{ +		handler();	// Fooey. +		return; +	} + +	cancel_sig(sig_left()); + +Alarm	*p; + +	for (p=first; p; p=p->next) +		if (p->set_interval > nseconds) +			break; + +	if (!p) +	{ +		next=0; +		if ((prev=last) != 0) +			prev->next=this; +		else +			first=this; +		last=this; +	} +	else +	{ +		if ((prev=p->prev) != 0) +			prev->next=this; +		else +			first=this; +		next=p; +		p->prev=this; +	} +	set_interval=nseconds; +	set_sig(); +} + +void Alarm::Cancel() +{ +	cancel_sig(sig_left()); +	if (set_interval) Unlink(); +	set_sig(); +} | 
