[Ace-users] Re: [ace-bugs] UUID_Generator
Douglas C. Schmidt
schmidt at dre.vanderbilt.edu
Sat Sep 1 16:14:20 CDT 2007
Hi Wim,
> Hereby I sent you the source files, see attachments.
Great, thanks!
> Maybe it is better to rename the method get_timestamp to
> get_timestampAndClocksequence.
I've tweaked things a bit to ensure backwards compatibility with
existing applications. Can you please check out
http://www.dre.vanderbilt.edu/~schmidt/DOC_ROOT/ACE/ace/UUID.h
http://www.dre.vanderbilt.edu/~schmidt/DOC_ROOT/ACE/ace/UUID.cpp
and let me know if it's ok? Also, could you please send me a brief
ChangeLog entry explaining what you've done and why.
Thanks very much,
Doug
> Kind regards,
>
> Wim van den Boogaard
> > Hi Wim,
> >
> > Thanks for using the PRF.
> >
> >
> >> ACE VERSION: 5.5.8 / 10
> >>
> >> HOST MACHINE and OPERATING SYSTEM:
> >> WinXP
> >>
> >> TARGET MACHINE and OPERATING SYSTEM, if different from HOST:
> >> COMPILER NAME AND VERSION (AND PATCHLEVEL):
> >>
> >> THE $ACE_ROOT/ace/config.h FILE [if you use a link to a platform-
> >> specific file, simply state which one]:
> >> config-win32.h
> >>
> >>
> >> THE $ACE_ROOT/include/makeinclude/platform_macros.GNU FILE [if you
> >> use a link to a platform-specific file, simply state which one
> >> (unless this isn't used in this case, e.g., with Microsoft Visual
> >> C++)]:
> >>
> >> CONTENTS OF $ACE_ROOT/bin/MakeProjectCreator/config/default.features
> >> (used by MPC when you generate your own makefiles):
> >> ---
> >>
> >> AREA/CLASS/EXAMPLE AFFECTED:
> >>
> >> DOES THE PROBLEM AFFECT:
> >> COMPILATION?
> >> LINKING
> >> EXECUTION
> >> OTHER (please specify)?
> >>
> >> SYNOPSIS:
> >> Double UUID generated in a multi threaded application.
> >>
> >> DESCRIPTION:
> >> The method UUID_Generator::generateUUID is not thread safe
> >> in respect to the combination uuid_state_.clockSequence
> >> and timestamp.
> >> The combination timestamp and clockSequence should be
> >> accessed in a thread safe manner. The method
> >> UUID_Generator::get_timestamp returns the timestamp thread
> >> safe, but also modifies the uuid_state_.clockSequence.
> >> The uuid_state_.clockSequence is accessed thread safe in
> >> UUID_Generator::generateUUID, but could have been modified
> >> between the moment get_timestamp is being done and the
> >> moment it is being used.
> >>
> >> REPEAT BY:
> >>
> >> SAMPLE FIX/WORKAROUND:
> >> Return the timestamp and clockSequence in a atomic manner
> >> via the get_timestamp method. I added an other argument
> >> to the get_timestamp.
> >> void get_timestamp(UUID_time& timestamp, ACE_UINT16& clockSequence);
> >>
> >> Return the actual clockSequence in the get_timestamp method.
> >>
> >
> > Could you please send the code that implements this and we'll add it to ACE!
> >
> > Thanks,
> >
> > Doug
> >
> >
>
> //$Id: UUID.cpp 78180 2007-04-25 07:05:02Z johnnyw $
>
> #include "ace/UUID.h"
> #include "ace/Guard_T.h"
>
> #if !defined (__ACE_INLINE__)
> #include "ace/UUID.inl"
> #endif /* __ACE_INLINE__ */
>
> #include "ace/Log_Msg.h"
> #include "ace/OS_NS_stdio.h"
> #include "ace/OS_NS_string.h"
> #include "ace/OS_NS_sys_time.h"
> #include "ace/OS_NS_netdb.h"
> #include "ace/OS_NS_unistd.h"
> #include "ace/ACE.h"
>
> ACE_RCSID (ace,
> UUID,
> "$Id: UUID.cpp 78180 2007-04-25 07:05:02Z johnnyw $")
>
>
> ACE_BEGIN_VERSIONED_NAMESPACE_DECL
>
> namespace ACE_Utils
> {
>
> UUID_node::UUID_node (void)
> {
> for (int i = 0; i < UUID_node::NODE_ID_SIZE; ++i)
> {
> nodeID_[i] = 0;
> }
> }
>
> UUID_node::NodeID&
> UUID_node::nodeID (void)
> {
> return nodeID_;
> }
>
> void
> UUID_node::nodeID (NodeID& nodeID)
> {
> for (int i = 0; i < UUID_node::NODE_ID_SIZE; ++i)
> {
> nodeID_[i] = nodeID[i];
> }
> }
>
> UUID UUID::NIL_UUID;
>
> /// Construct a nil UUID. Such a UUID has every one of it's data
> /// elements set to zero.
> UUID::UUID(void)
> : timeLow_ (0),
> timeMid_ (0),
> timeHiAndVersion_ (0),
> clockSeqHiAndReserved_ (0),
> clockSeqLow_ (0),
> node_ (0),
> node_release_ (true),
> as_string_ (0)
> {
> ACE_NEW (node_,
> UUID_node);
> }
>
> /// Construct a UUID from a string representation of an UUID.
> UUID::UUID (const ACE_CString& uuid_string)
> : timeLow_ (0),
> timeMid_ (0),
> timeHiAndVersion_ (0),
> clockSeqHiAndReserved_ (0),
> clockSeqLow_ (0),
> node_ (0),
> node_release_ (true),
> as_string_ (0)
> {
> ACE_NEW (node_,
> UUID_node);
>
> this->from_string_i (uuid_string);
> }
>
> UUID::UUID(const UUID &right)
> : timeLow_ (right.timeLow_),
> timeMid_ (right.timeMid_),
> timeHiAndVersion_ (right.timeHiAndVersion_),
> clockSeqHiAndReserved_ (right.clockSeqHiAndReserved_),
> clockSeqLow_ (right.clockSeqLow_),
> as_string_ (0)
> {
> ACE_NEW (node_,
> UUID_node (*right.node_));
> }
>
> UUID::~UUID (void)
> {
> if (node_release_)
> delete node_;
>
> if (as_string_ != 0)
> delete as_string_;
> }
>
> const ACE_CString*
> UUID::to_string (void)
> {
> /// Only compute the string representation once.
> if (as_string_ == 0)
> {
> // Get a buffer exactly the correct size. Use the nil UUID as a
> // gauge. Don't forget the trailing nul.
> size_t UUID_STRING_LENGTH = 36 + thr_id_.length () + pid_.length ();
> char *buf = 0;
>
> if ((thr_id_.length () != 0) && (pid_.length () != 0))
> {
> UUID_STRING_LENGTH += 2; //for '-'
> ACE_NEW_RETURN (buf,
> char[UUID_STRING_LENGTH + 1],
> 0);
>
> ACE_OS::sprintf(buf,
> "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x-%s-%s",
> this->timeLow_,
> this->timeMid_,
> this->timeHiAndVersion_,
> this->clockSeqHiAndReserved_,
> this->clockSeqLow_,
> (this->node_->nodeID ()) [0],
> (this->node_->nodeID ()) [1],
> (this->node_->nodeID ()) [2],
> (this->node_->nodeID ()) [3],
> (this->node_->nodeID ()) [4],
> (this->node_->nodeID ()) [5],
> thr_id_.c_str (),
> pid_.c_str ()
> );
> }
> else
> {
> ACE_NEW_RETURN (buf,
> char[UUID_STRING_LENGTH + 1],
> 0);
>
> ACE_OS::sprintf (buf,
> "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
> this->timeLow_,
> this->timeMid_,
> this->timeHiAndVersion_,
> this->clockSeqHiAndReserved_,
> this->clockSeqLow_,
> (this->node_->nodeID ()) [0],
> (this->node_->nodeID ()) [1],
> (this->node_->nodeID ()) [2],
> (this->node_->nodeID ()) [3],
> (this->node_->nodeID ()) [4],
> (this->node_->nodeID ()) [5]
> );
> }
>
> // We allocated 'buf' above dynamically, so we shouldn't use
> // ACE_NEW_RETURN here to avoid a possible memory leak.
> ACE_NEW_NORETURN (this->as_string_,
> ACE_CString (buf, UUID_STRING_LENGTH));
>
> // we first free the dynamically allocated 'buf'.
> delete [] buf;
>
> // then we test that ACE_NEW succeded for 'as_string_'
> // if not, we return 0 (NULL) to indicate failure.
> if( this->as_string_ == 0 )
> {
> return 0;
> }
> }
>
> return as_string_;
> }
>
> void
> UUID::from_string_i (const ACE_CString& uuid_string)
> {
> if (uuid_string.length() < NIL_UUID.to_string ()->length ())
> {
> ACE_ERROR ((LM_ERROR,
> "%N ACE_UUID::from_string_i - "
> "IllegalArgument(incorrect string length)\n"));
> return;
> }
>
> /// Special case for the nil UUID.
> if (uuid_string == *NIL_UUID.to_string ())
> {
> bool copy_constructor_not_supported = false;
> ACE_ASSERT (copy_constructor_not_supported);
> //*this = NIL_UUID;
> ACE_UNUSED_ARG (copy_constructor_not_supported);
> return;
> }
>
> unsigned int timeLow;
> unsigned int timeMid;
> unsigned int timeHiAndVersion;
> unsigned int clockSeqHiAndReserved;
> unsigned int clockSeqLow;
> unsigned int node [UUID_node::NODE_ID_SIZE];
> char thr_pid_buf [BUFSIZ];
>
> if (uuid_string.length() == NIL_UUID.to_string()->length())
> {
> // This might seem quite strange this being in ACE, but it
> // seems to be a bit difficult to write a facade for ::sscanf
> // because some compilers dont support vsscanf, including
> // MSVC. It appears that most platforms support sscanf though
> // so we need to use it directly.
> const int nScanned =
> #if defined (ACE_HAS_TR24731_2005_CRT)
> sscanf_s (
> #else
> ::sscanf(
> #endif
> uuid_string.c_str(),
> "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x",
> &timeLow,
> &timeMid,
> &timeHiAndVersion,
> &clockSeqHiAndReserved,
> &clockSeqLow,
> &node[0],
> &node[1],
> &node[2],
> &node[3],
> &node[4],
> &node[5]
> );
>
> if (nScanned != 11)
> {
> ACE_DEBUG ((LM_DEBUG,
> "UUID::from_string_i - "
> "IllegalArgument(invalid string representation)\n"));
> return;
> }
> }
> else
> {
> const int nScanned =
> #if defined (ACE_HAS_TR24731_2005_CRT)
> sscanf_s (uuid_string.c_str(),
> "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s",
> &timeLow,
> &timeMid,
> &timeHiAndVersion,
> &clockSeqHiAndReserved,
> &clockSeqLow,
> &node[0],
> &node[1],
> &node[2],
> &node[3],
> &node[4],
> &node[5],
> thr_pid_buf,
> BUFSIZ
> );
> #else
> ::sscanf (uuid_string.c_str(),
> "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s",
> &timeLow,
> &timeMid,
> &timeHiAndVersion,
> &clockSeqHiAndReserved,
> &clockSeqLow,
> &node[0],
> &node[1],
> &node[2],
> &node[3],
> &node[4],
> &node[5],
> thr_pid_buf
> );
> #endif /* ACE_HAS_TR24731_2005_CRT */
>
> if (nScanned != 12)
> {
> ACE_DEBUG ((LM_DEBUG,
> "ACE_UUID::from_string_i - "
> "IllegalArgument(invalid string representation)\n"));
> return;
> }
> }
>
> this->timeLow_ = static_cast<ACE_UINT32> (timeLow);
> this->timeMid_ = static_cast<ACE_UINT16> (timeMid);
> this->timeHiAndVersion_ = static_cast<ACE_UINT16> (timeHiAndVersion);
> this->clockSeqHiAndReserved_ = static_cast<u_char> (clockSeqHiAndReserved);
> this->clockSeqLow_ = static_cast<u_char> (clockSeqLow);
>
> UUID_node::NodeID nodeID;
> for (int i = 0; i < UUID_node::NODE_ID_SIZE; ++i)
> nodeID [i] = static_cast<u_char> (node[i]);
>
> this->node_->nodeID (nodeID);
>
> // Support varient 10- only
> if ((this->clockSeqHiAndReserved_ & 0xc0) != 0x80 && (this->clockSeqHiAndReserved_ & 0xc0) != 0xc0)
> {
> ACE_DEBUG ((LM_DEBUG,
> "ACE_UUID::from_string_i - "
> "IllegalArgument(unsupported variant)\n"));
> return;
> }
>
> /// Support versions 1, 3, and 4 only
> ACE_UINT16 V1 = this->timeHiAndVersion_;
>
> if ((V1 & 0xF000) != 0x1000 &&
> (V1 & 0xF000) != 0x3000 &&
> (V1 & 0xF000) != 0x4000)
> {
> ACE_DEBUG ((LM_DEBUG,
> "ACE_UUID::from_string_i - "
> "IllegalArgument(unsupported version)\n"));
> return;
> }
> if ((this->clockSeqHiAndReserved_ & 0xc0) == 0xc0)
> {
> if (uuid_string.length() == NIL_UUID.to_string()->length())
> {
> ACE_DEBUG ((LM_DEBUG,
> "ACE_UUID::from_string_i - "
> "IllegalArgument (Missing Thread and Process Id)\n"));
> return;
> }
> ACE_CString thr_pid_str (thr_pid_buf);
> ssize_t pos = static_cast<ssize_t> (thr_pid_str.find ('-'));
> if (pos == -1)
> ACE_DEBUG ((LM_DEBUG,
> "ACE_UUID::from_string_i - "
> "IllegalArgument (Thread and Process Id format incorrect)\n"));
>
> this->thr_id_ = thr_pid_str.substr (0, pos);
> this->pid_ = thr_pid_str.substr (pos+1, thr_pid_str.length ()-pos-1);
> }
> }
>
> UUID_Generator::UUID_Generator ()
> : timeLast_ (0),
> destroy_lock_ (true)
> {
> ACE_NEW (lock_,
> ACE_SYNCH_MUTEX);
> }
>
> UUID_Generator::~UUID_Generator()
> {
> if (destroy_lock_)
> delete lock_;
> }
>
> void
> UUID_Generator::init (void)
> {
> ACE_OS::macaddr_node_t macaddress;
> int result = ACE_OS::getmacaddress (&macaddress);
>
> UUID_node::NodeID nodeID;
> if (result != -1)
> {
> // ACE_DEBUG ((LM_DEBUG,
> // "%02X-%02X-%02X-%02X-%02X-%02X\n",
> // macaddress.node [0],
> // macaddress.node [1],
> // macaddress.node [2],
> // macaddress.node [3],
> // macaddress.node [4],
> // macaddress.node [5]));
>
> ACE_OS::memcpy (&nodeID,
> macaddress.node,
> sizeof (nodeID));
> }
> else
> {
> nodeID [0] = static_cast<u_char> (ACE_OS::rand());
> nodeID [1] = static_cast<u_char> (ACE_OS::rand());
> nodeID [2] = static_cast<u_char> (ACE_OS::rand());
> nodeID [3] = static_cast<u_char> (ACE_OS::rand());
> nodeID [4] = static_cast<u_char> (ACE_OS::rand());
> nodeID [5] = static_cast<u_char> (ACE_OS::rand());
> }
>
> ACE_UINT16 dummy;
> this->get_timestamp (timeLast_,dummy);
>
> {
> ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, *lock_);
> uuid_state_.timestamp = timeLast_;
> uuid_state_.node.nodeID (nodeID);
> }
> }
>
>
> void
> UUID_Generator::generateUUID (UUID& uuid,ACE_UINT16 version, u_char variant)
> {
> UUID_time timestamp;
> ACE_UINT16 clockSequence;
> this->get_timestamp (timestamp,clockSequence);
>
>
> // Construct a Version 1 UUID with the information in the arguements.
> uuid.timeLow (static_cast<ACE_UINT32> (timestamp & 0xFFFFFFFF));
> uuid.timeMid (static_cast<ACE_UINT16> ((timestamp >> 32) & 0xFFFF));
>
>
> ACE_UINT16 tHAV = static_cast<ACE_UINT16> ((timestamp >> 48) & 0xFFFF);
> tHAV |= (version << 12);
> uuid.timeHiAndVersion (tHAV);
>
> u_char cseqHAV;
> uuid.clockSeqLow (static_cast<u_char> (clockSequence & 0xFF));
> cseqHAV = static_cast<u_char> ((clockSequence & 0x3f00) >> 8);
> uuid_state_.timestamp = timestamp;
>
> cseqHAV |= variant;
> uuid.clockSeqHiAndReserved (cseqHAV);
> uuid.node (&(uuid_state_.node));
>
> if (variant == 0xc0)
> {
> ACE_Thread_ID thread_id;
> char buf [BUFSIZ];
> thread_id.to_string (buf);
> uuid.thr_id (buf);
>
> ACE_OS::sprintf (buf,
> "%d",
> static_cast<int> (ACE_OS::getpid ()));
> uuid.pid (buf);
> }
> }
>
> UUID*
> UUID_Generator::generateUUID (ACE_UINT16 version, u_char variant)
> {
> UUID* uuid;
> ACE_NEW_RETURN (uuid,
> UUID,
> 0);
>
> this->generateUUID (*uuid, version, variant);
> return uuid;
> }
>
> /// Obtain a new timestamp. If UUID's are being generated too quickly
> /// the clock sequence will be incremented
> void
> UUID_Generator::get_timestamp (UUID_time& timestamp,ACE_UINT16& clockSequence)
> {
> ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_);
>
> this->get_systemtime(timestamp);
>
> // Account for the clock being set back. Increment the clock /
> // sequence.
> if (timestamp <= timeLast_)
> uuid_state_.clockSequence = static_cast<u_char> ((uuid_state_.clockSequence + 1) & ACE_UUID_CLOCK_SEQ_MASK);
>
> // If the system time ticked since the last UUID was
> // generated. Set / the clock sequence back.
> else if (timestamp > timeLast_)
> uuid_state_.clockSequence = 0;
>
> timeLast_ = timestamp;
> clockSequence = uuid_state_.clockSequence;
> }
>
> /**
> * ACE_Time_Value is in POSIX time, seconds since Jan 1, 1970. UUIDs use
> * time in 100ns ticks since 15 October 1582. The difference is:
> * 15 Oct 1582 - 1 Jan 1600: 17 days in Oct, 30 in Nov, 31 in Dec +
> * 17 years and 4 leap days (1584, 88, 92 and 96)
> * 1 Jan 1600 - 1 Jan 1900: 3 centuries + 73 leap days ( 25 in 17th cent.
> * and 24 each in 18th and 19th centuries)
> * 1 Jan 1900 - 1 Jan 1970: 70 years + 17 leap days.
> * This adds up, in days: (17+30+31+365*17+4)+(365*300+73)+(365*70+17) or
> * 122192928000000000U (0x1B21DD213814000) 100 ns ticks.
> */
> void
> UUID_Generator::get_systemtime (UUID_time & timestamp)
> {
> const UUID_time timeOffset =
> #if defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
> ACE_U_LongLong (ACE_INT64_LITERAL (0x1B21DD213814000));
> #elif defined (ACE_LACKS_LONGLONG_T)
> ACE_U_LongLong (0x13814000u, 0x1B21DD2u);
> #else
> ACE_UINT64_LITERAL (0x1B21DD213814000);
> #endif /* ACE_LACKS_UNSIGNEDLONGLONG_T */
>
> /// Get the time of day, convert to 100ns ticks then add the offset.
> ACE_Time_Value now = ACE_OS::gettimeofday();
> ACE_UINT64 time;
> now.to_usec (time);
> time = time * 10;
> timestamp = time + timeOffset;
> }
>
> ACE_SYNCH_MUTEX*
> UUID_Generator::lock (void)
> {
> return this->lock_;
> }
>
> void
> UUID_Generator::lock (ACE_SYNCH_MUTEX* lock,
> bool release_lock)
> {
> if (this->destroy_lock_)
> delete this->lock_;
>
> this->lock_ = lock;
> this->destroy_lock_ = release_lock;
> }
>
> }
>
> #if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
> template ACE_Singleton<ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX> *
> ACE_Singleton<ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX>::singleton_;
> #endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
>
> ACE_END_VERSIONED_NAMESPACE_DECL
> // -*- C++ -*-
>
> //=============================================================================
> /**
> * @file UUID.h
> *
> * $Id: UUID.h 74958 2006-10-23 23:31:00Z ossama $
> *
> * @author Andrew T. Finnel <andrew at activesol.net>
> * @author Yamuna Krishnmaurthy <yamuna at oomworks.com>
> */
> //=============================================================================
>
> #ifndef ACE_UUID_H
> #define ACE_UUID_H
> #include /**/ "ace/pre.h"
>
> #include /**/ "ace/config-all.h"
>
> #if !defined (ACE_LACKS_PRAGMA_ONCE)
> # pragma once
> #endif /* ACE_LACKS_PRAGMA_ONCE */
>
> #include "ace/SString.h"
> #include "ace/Singleton.h"
> #include "ace/Synch_Traits.h"
>
> ACE_BEGIN_VERSIONED_NAMESPACE_DECL
>
> namespace ACE_Utils
> {
> /// Class to hold a MAC address
> class ACE_Export UUID_node
> {
> public:
>
> /// Constructor
> UUID_node (void);
>
> enum {NODE_ID_SIZE = 6};
> typedef u_char NodeID[NODE_ID_SIZE];
>
> NodeID& nodeID (void);
> void nodeID (NodeID&);
>
> ///// Equality Operations
> bool operator == (const UUID_node& right) const;
> bool operator != (const UUID_node& right) const;
>
> ///// Relational Operations
> //bool operator < (const UUID_node& right) const;
>
> private:
> NodeID nodeID_;
> };
>
>
>
> /**
> * @class ACE_UUID
> *
> * ACE_UUID represents a Universally Unique IDentifier (UUID) as
> * described in (the expired) INTERNET-DRAFT specification entitled
> * UUIDs and GUIDs. All instances of UUID are of the time-based
> * variety. That is, the version number part of the timeHiAndVersion
> * field is 1.
> *
> * The default constructor creates a nil UUID.
> *
> * UUIDs have value semantics. In addition, they may be compared for
> * ordering and equality.
> *
> * Additionally in this implementation provisions have been made to include
> * process and thread ids to make the UUIDs more unique. The variant 0xc0
> * has been added to facilitate this.
> */
> class ACE_Export UUID
> {
> public:
>
> /// Constructor
> UUID (void);
>
> /// Constructs a UUID from a string representation.
> UUID (const ACE_CString& uuidString);
>
> UUID (const UUID &right);
>
> // Destructor
> ~UUID (void);
>
> ACE_UINT32 timeLow (void) const;
> void timeLow (ACE_UINT32);
>
> ACE_UINT16 timeMid (void) const;
> void timeMid (ACE_UINT16);
>
> ACE_UINT16 timeHiAndVersion (void) const;
> void timeHiAndVersion (ACE_UINT16);
>
> u_char clockSeqHiAndReserved (void) const;
> void clockSeqHiAndReserved (u_char);
>
> u_char clockSeqLow (void) const;
> void clockSeqLow (u_char);
>
> UUID_node* node (void) const;
> void node (UUID_node*);
>
> ACE_CString* thr_id (void);
> void thr_id (char*);
>
> ACE_CString* pid (void);
> void pid (char*);
>
> /// Returns a string representation of the UUID
> const ACE_CString* to_string (void);
>
> /// Set the value using a string
> void from_string (const ACE_CString& uuid_string);
>
> static UUID NIL_UUID;
>
> /// Equality Operations
> bool operator== (const UUID &right) const;
> bool operator!= (const UUID &right) const;
>
> /// Relational Operations
> //bool operator< (const UUID &right) const;
> //bool operator> (const UUID &right) const;
> //bool operator<= (const UUID &right) const;
> //bool operator>= (const UUID &right) const;
>
> private:
> void from_string_i (const ACE_CString& uuidString);
>
> UUID& operator= (const UUID&);
>
> /// Data Members for Class Attributes
> ACE_UINT32 timeLow_;
> ACE_UINT16 timeMid_;
> ACE_UINT16 timeHiAndVersion_;
> u_char clockSeqHiAndReserved_;
> u_char clockSeqLow_;
> UUID_node* node_;
> bool node_release_;
> ACE_CString thr_id_;
> ACE_CString pid_;
>
> /// The string representation of the UUID. This is created and
> /// updated only on demand.
> ACE_CString *as_string_;
> };
>
>
> /**
> * @class ACE_UUID_Generator
> *
> * Singleton class that generates UUIDs.
> *
> */
> class ACE_Export UUID_Generator
> {
> public:
>
> enum {ACE_UUID_CLOCK_SEQ_MASK = 0x3FFF};
>
> UUID_Generator();
> ~UUID_Generator();
>
> void init (void);
>
> /// Format timestamp, clockseq, and nodeID into an UUID of the
> /// specified version and variant. For generating UUID's with
> /// thread and process ids use variant=0xc0
> void generateUUID (UUID&, ACE_UINT16 version=0x0001, u_char variant=0x80);
>
> /// Format timestamp, clockseq, and nodeID into a VI UUID. For
> /// generating UUID's with thread and process ids use variant=0xc0
> UUID* generateUUID (ACE_UINT16 version=0x0001, u_char variant=0x80);
>
> /// Type to represent UTC as a count of 100 nanosecond intervals
> /// since 00:00:00.00, 15 October 1582.
> typedef ACE_UINT64 UUID_time;
>
> /// The locking strategy prevents multiple generators from accessing
> /// the UUID_state at the same time. Get the locking strategy.
> ACE_SYNCH_MUTEX* lock (void);
>
> /// Set a new locking strategy and return the old one.
> void lock (ACE_SYNCH_MUTEX* lock,
> bool release_lock);
>
> private:
>
> /// The system time when that last uuid was generated.
> UUID_time timeLast_;
>
> /// Type to contain the UUID generator persistent state. This will
> /// be kept in memory mapped shared memory
> struct UUID_State
> {
> UUID_time timestamp;
> UUID_node node;
> ACE_UINT16 clockSequence;
> };
>
> /// Obtain a UUID timestamp. Compensate for the fact that the time
> /// obtained from getSystem time has a resolution less than 100ns.
> void get_timestamp (UUID_time& timestamp, ACE_UINT16& clockSequence);
>
> /// Obtain the system time in UTC as a count of 100 nanosecond intervals
> /// since 00:00:00.00, 15 October 1582 (the date of Gregorian reform to
> /// the Christian calendar).
> void get_systemtime( UUID_time& timeNow);
>
> /// The UUID generator persistent state.
> UUID_State uuid_state_;
>
> ACE_SYNCH_MUTEX* lock_;
> bool destroy_lock_;
> };
>
> typedef ACE_Singleton<UUID_Generator, ACE_SYNCH_MUTEX> UUID_GENERATOR;
>
> }
>
> ACE_END_VERSIONED_NAMESPACE_DECL
>
> #if defined (__ACE_INLINE__)
> #include "ace/UUID.inl"
> #endif /* __ACE_INLINE__ */
>
> #include /**/ "ace/post.h"
> #endif // ACE_UUID_H
More information about the Ace-users
mailing list