/* Web Polygraph http://www.web-polygraph.org/ * (C) 2003-2006 The Measurement Factory * Licensed under the Apache License, Version 2.0 */ #ifndef POLYGRAPH__BASE_UNIQID_H #define POLYGRAPH__BASE_UNIQID_H #include "xstd/h/iosfwd.h" class Area; class String; class OLog; class ILog; class OBStream; class IBStream; // we often need an id with these characteristics: // - truly unique across hosts, processes, time (within ttl), etc // - at least one year ttl // - compact to store // - fast to produce [possibly in huge quantaties!] // - fast to compare on equality // - has one and only one "permutated" value that // cannot be generated by means other than "mutating" an id class UniqId { public: static UniqId Create() { return UniqId().create(); } static void Space(int id); // generate ids in a given space static UniqId FromStr(const Area &area); public: UniqId(); UniqId(int aSecs, int aMix, int aCnt); void clear() { theCnt = 0; } UniqId &create(); // returns itself operator void*() const { return theCnt > 0 ? (void*)-1 : 0; } // created? bool mutant() const { return theCnt & 1; } // is a mutatant? inline bool myMutant(const UniqId &mid) const; inline UniqId genMutant() const; // produce a mutant // returns a not so unique integer int hash() const; String str() const; inline bool operator ==(const UniqId &id) const; inline bool operator !=(const UniqId &id) const; inline bool operator <(const UniqId &id) const; // arbirtary order ostream &print(ostream &os) const; OLog &store(OLog &ol) const; ILog &load(ILog &il); OBStream &store(OBStream &os) const; IBStream &load(IBStream &is); protected: void RefreshSessionId(); protected: int theSecs; // seconds since Nov 29 06:21:18 MST 1998 (or space XXX) int theMix; // usec and process id int theCnt; // instance }; /* inline definitions */ inline ostream &operator <<(ostream &os, const UniqId &id) { return id.print(os); } inline OLog &operator <<(OLog &ol, const UniqId &id) { return id.store(ol); } inline ILog &operator >>(ILog &il, UniqId &id) { return id.load(il); } inline OBStream &operator <<(OBStream &os, const UniqId &id) { return id.store(os); } inline IBStream &operator >>(IBStream &is, UniqId &id) { return id.load(is); } inline UniqId UniqId::genMutant() const { return UniqId(theSecs, theMix, ~theCnt & 0x7fffffff); } inline bool UniqId::myMutant(const UniqId &m) const { return (m.theCnt == (~theCnt & 0x7fffffff)) && theMix == m.theMix && theSecs == m.theSecs; } inline bool UniqId::operator ==(const UniqId &id) const { return theCnt == id.theCnt && // most selective first theMix == id.theMix && theSecs == id.theSecs; } inline bool UniqId::operator !=(const UniqId &id) const { return !(*this == id); } inline bool UniqId::operator <(const UniqId &id) const { if (theCnt < id.theCnt) return true; if (theCnt > id.theCnt) return false; if (theMix < id.theMix) return true; if (theMix > id.theMix) return false; return theSecs < id.theSecs; } #endif