[ace-users] [ace-bugs] UUID_Generator
Johnny Willemsen
jwillemsen at remedy.nl
Mon Sep 3 08:03:23 CDT 2007
Hi,
> ok, great, thanks for all the improvements and documentation. I'll
> check this in after the x.6 release goes out tomorrow.
>
> BTW, Johnny, I've made a pass through UUID.{h,inl,cpp} and
> "ACE-ified" everything. This may require some changes to user code,
> but the original API was totally inconsistent with ACE.
Could we keep the API the same for x.6.1? Break it after that version? I
think CIAO, the COIOP pluggable protocol in TAO and the regression test
under ACE_wrappers/tests do use UUID directly.
Johnny
> >>
> >> 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
> >>>
> >>
> >>
> >
>
>
> --
> Dr. Douglas C. Schmidt Professor and
> Associate Chair
> Electrical Engineering and Computer Science TEL: (615) 343-8197
> Vanderbilt University WEB:
> www.dre.vanderbilt.edu/~schmidt
> Nashville, TN 37203 NET:
> d.schmidt at vanderbilt.edu
>
> _______________________________________________
> ace-users mailing list
> ace-users at mail.cse.wustl.edu
> http://mail.cse.wustl.edu/mailman/listinfo/ace-users
>
More information about the Ace-users
mailing list