/*
 *
 *	$Header: /usr/u/wjr/src/ADT/RCS/counter.c,v 1.4 1991/11/07 22:41:46 wjr Exp $
 *
 */
/*
 * Xerox may use this code without restriction.
 */

static char *rcsid = "@(#)$Header: /usr/u/wjr/src/ADT/RCS/counter.c,v 1.4 1991/11/07 22:41:46 wjr Exp $";

/*
 * A Counter is a large counter, used to ensure FIFO ordering. Whenever
 * something is added to a queue, the current Counter value for that
 * queue is made part of its structure, and the Counter is incremented.
 */
/*
 *	counter.c - Large Counters
 *
 * This module handles counters: things which can be incremented for a
 * very long time without overflowing. A Counter ought to be able to be
 * incremented at the maximum machine rate for longer than the projected
 * lifetime of the machine while still giving a sequence of constantly
 * increasing values.
 *
 * Exports:
 *	type Counter
 *
 *	void coInit(Counter *c) - initialise c to the lowest possible value
 *
 *	void coInc(Counter *c) - increment c to the next value
 *
 *	boolean coGT(Counter *c1, Counter *c2) - determine if c1 > c2
 *
 *	boolean coEQ(Counter *c1, Counter *c2) - determine if c1 == c2
 *
 *	boolean coCopy(Counter *d, counter *s) - copy s into d
 *
 * An object of type Counter is used to hold a count of something.
 *
 * coInit initialises a Counter, resetting it to "zero". A Counter must
 *	be initialised by coInit before it can be used. The value of a
 *	Counter just initialised by coInit will not be larger than any
 *	other Counter value (as tested by coGT).
 *
 * coInc increments a Counter. It will then contain the successor
 *	of its previous value, and will be larger than it, as tested
 *	by coGT.
 *
 * coGT compares two Counters. It returns TRUE if c1 > c2, and FALSE if
 *	c1 <= c2. c1 will be greater than c2 if coInc has been called on c1
 *	strictly more times than it has been called on c2 (since each was
 *	initialised).
 *
 * coEQ compares two counters. It returns TRUE if c1 == c2 and FALSE
 *	otherwise. c1 and c2 will be equal if coInc has been called on
 *	c1 the same number of times as it has been called on c2. If a counter
 *	is copied using coCopy, the two counters will compare as equal with
 *	coEQ.
 *
 * coCopy copies a Counter's value. The destination now contains the same
 *	value as the source. The destination
 *	need not be initialised (though the pointer must point at correctly
 *	allocated memory!). The destination's old value is overwritten.
 *
 */

#include "misc.h"
#include "counter.h"

void
coInit(Counter *c)
{
    assert(c != (Counter *)NULL);
    c->lsw = c->msw = 0;
    }

void
coInc(Counter *c)
{
    assert(c != (Counter *)NULL);
    (c->lsw)++;
    if (c->lsw == 0) {
	(c->msw)++;
	}
    }

boolean
coGT(Counter *c1, Counter *c2)
{
    assert(c1 != (Counter *)NULL);
    assert(c2 != (Counter *)NULL);
    if ((c1->msw > c2->msw) ||
	((c1->msw == c2->msw) && (c1->lsw > c2->lsw))) {
	return(TRUE);
	}
    else {
	return(FALSE);
	}
    }

boolean
coEQ(Counter *c1, Counter *c2)
{
    assert(c1 != (Counter *)NULL);
    assert(c2 != (Counter *)NULL);
    if ((c1->msw == c2->msw) && (c1->lsw == c2->lsw)) {
	return(TRUE);
	}
    else {
	return(FALSE);
	}
    }

void
coCopy(Counter *d, Counter *s)
{
    assert(d != (Counter *)NULL);
    assert(s != (Counter *)NULL);
    d->lsw = s->lsw;
    d->msw = s->msw;
    }
