(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Last Modified On Thu Nov 2 18:19:26 1989 by muller *) (* Modified On Fri Sep 29 09:33:36 1989 by kalsow *) (* Modified on Thu Mar 30 18:27:39 1989 by hisgen *) (* Modified on Thu Dec 22 16:01:27 1988 by swart *) (* Modified On Fri Jun 3 10:17:00 PDT 1988 by glassman *) (* Modified On Mon Oct 13 16:37:22 1986 By levin *) INTERFACE UID; (************************************************************************) (* A centralized source of unique identifiers (UIDs) *) (* *) (* UID serves as a centralized source of unique identifiers (UIDs). *) (* A UID consists of a 31-bit value that is unique across time on *) (* a particular machine, plus a constant value that uniquely identifies *) (* the machine. UIDs are used in version stamping, among other things. *) (* *) (* Index: unique identifiers; version stamping *) (************************************************************************) TYPE Counter = CARDINAL; TYPE FineCounter = RECORD coarse: Counter; fine: [0..65535]; END; TYPE Constant = ARRAY [0..5] OF [0..255]; TYPE T = RECORD machine: Constant; counter: FineCounter; END; TYPE ID = RECORD machine: Constant; counter: Counter; END; (* IDs should be used only when the rate of object generation is known to be quite infrequent. *) TYPE Capability = RECORD id: T; random1, random2: INTEGER; END; (* The 64 random bits make capabilities hard to guess. *) (*****************************************************************************) (* A note on uniqueness: The implementations of 'GetCounter' and *) (* 'GetFineCounter' use the real-time clock and assume that time flows *) (* monotonically. Consequently, if 'Time.SetNow' is used to move the *) (* real-time clock "backwards in time", the uniqueness guarantee of this *) (* interface may be compromised. Normally, 'Time.SetNow' will only be *) (* used to move the clock "forward in time", i.e., when 'Time.ClockIsOK' *) (* has returned FALSE. This cannot compromise the uniqueness of the *) (* values returned by the procedures below. *) (*****************************************************************************) PROCEDURE Get (VAR (*OUT*) t: T) RAISES {}; (* == GetConstant (t.machine); GetFineCounter (t.counter). This procedure provides a centralized source of unique IDs, that is, values that are unique across time and machines. *) PROCEDURE GetCounter (): Counter; (* This procedure provides a centralized source of unique numbers, that is, 31-bit values that are unique across time on this machine. To obtain a true unique identifier, call 'Get'. 'GetCounter' guarantees to deliver values at a sustained rate of one per second, but typically does so considerably faster. If lower latency is required, the client should use 'GetFineCounter'. *) PROCEDURE GetFineCounter (VAR c: FineCounter); (* This procedure enables the client to avoid the potential latency of 'GetCounter'. 'GetFineCounter' can deliver unique 47-bit values at the sustained rate of 2^16 values per second (if only the CPU were that fast!). Note: 'GetFineCounter' can be used to produce timestamps, since the value returned in 'c.coarse' is 'Time.NowSeconds()'. *) PROCEDURE GetConstant (VAR c: Constant); (* This procedure returns a 48-bit quantity that is unique to the machine on which it is called. This value is constant for a given machine throughout time, unless hardware modifications are made. *) PROCEDURE GetID (VAR (*OUT*) id: ID) RAISES {}; (* == GetConstant (t.machine); t.counter := GetFineCounter (). *) PROCEDURE GetCapability (VAR (*OUT*) cap: Capability) RAISES {}; (* == Get (cap.id); cap.random1 := Random.Integer (); cap.random2 := Random.Integer (); *) PROCEDURE EqualT (READONLY t1, t2: T): BOOLEAN RAISES {}; PROCEDURE EqualID (READONLY id1, id2: ID): BOOLEAN RAISES {}; PROCEDURE EqualCapability (READONLY c1, c2: Capability): BOOLEAN RAISES {}; PROCEDURE EqualConstant (READONLY c1, c2: Constant): BOOLEAN RAISES {}; PROCEDURE EqualFineCounter (READONLY c1, c2: FineCounter): BOOLEAN RAISES {}; (* All of the "Compare" procedures return a value less than zero if "a < b" is true, zero if "a = b" is true, or a value greater than zero if "a > b". Also, if all you care about is equality, the "Equal" procedures are probably more efficient.*) PROCEDURE CompareCounter (a, b: Counter): INTEGER RAISES {}; (* This procedure exists only for completeness. Counters are CARDINALs, and can be compared directly.*) PROCEDURE CompareFineCounter (a, b: FineCounter): INTEGER RAISES {}; (* Order of comparison is "coarse" field first, then "fine" field.*) PROCEDURE CompareConstant (a, b: Constant): INTEGER RAISES {}; (* Order of comparison is bytes 0 thru 5, where each byte is compared as an unsigned number.*) PROCEDURE CompareT (a, b: T): INTEGER RAISES {}; (* Order of comparison is "counter" field first, then "machine" field.*) PROCEDURE CompareID (a, b: ID): INTEGER RAISES {}; (* Order of comparison is "counter" field first, then "machine" field.*) PROCEDURE CompareCapability (a, b: Capability): INTEGER RAISES {}; (* Order of comparison is "id" field first, then "random1", then "random2".*) PROCEDURE CompareInteger (a, b: INTEGER): INTEGER RAISES {}; (* Here for convenience.*) END UID.