Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:54:01

0001 #ifndef BOOST_UUID_TIME_GENERATOR_V1_HPP_INCLUDED
0002 #define BOOST_UUID_TIME_GENERATOR_V1_HPP_INCLUDED
0003 
0004 // Copyright 2024 Peter Dimov
0005 // Distributed under the Boost Software License, Version 1.0.
0006 // https://www.boost.org/LICENSE_1_0.txt
0007 
0008 #include <boost/uuid/uuid.hpp>
0009 #include <boost/uuid/uuid_clock.hpp>
0010 #include <boost/uuid/detail/random_provider.hpp>
0011 #include <boost/uuid/detail/endian.hpp>
0012 #include <boost/config.hpp>
0013 #include <boost/config/workaround.hpp>
0014 #include <atomic>
0015 #include <cstdint>
0016 #include <cstring>
0017 
0018 namespace boost {
0019 namespace uuids {
0020 
0021 // time_generator_v1
0022 
0023 class time_generator_v1
0024 {
0025 public:
0026 
0027     struct state_type
0028     {
0029         std::uint64_t timestamp;
0030         std::uint16_t clock_seq;
0031 
0032 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114865
0033 #if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION, >= 130000)
0034 # if BOOST_CXX_VERSION >= 201402L
0035 
0036         std::uint16_t padding[ 3 ] = {};
0037 
0038 # else
0039 
0040         std::uint16_t padding[ 3 ];
0041 
0042 # endif
0043 #endif
0044     };
0045 
0046 private:
0047 
0048     uuid::node_type node_ = {{}};
0049 
0050     std::atomic<state_type>* ps_ = nullptr;
0051 
0052 #if BOOST_WORKAROUND(BOOST_GCC, < 50000)
0053 
0054     // Avoid -Wmissing-field-initializers under GCC 4.x
0055     state_type state_ = { 0, 0 };
0056 
0057 #else
0058 
0059     state_type state_ = {};
0060 
0061 #endif
0062 
0063 public:
0064 
0065     using result_type = uuid;
0066 
0067     time_generator_v1();
0068     time_generator_v1( uuid::node_type const& node, state_type const& state ) noexcept;
0069     time_generator_v1( uuid::node_type const& node, std::atomic<state_type>& state ) noexcept;
0070 
0071     result_type operator()() noexcept;
0072 
0073 private:
0074 
0075     static state_type get_new_state( state_type const& oldst ) noexcept;
0076 };
0077 
0078 // constructors
0079 
0080 inline time_generator_v1::time_generator_v1()
0081 {
0082     detail::random_provider prov;
0083 
0084     // generate a pseudorandom node identifier
0085 
0086     std::uint32_t tmp[ 3 ];
0087     prov.generate( tmp, tmp + 3 );
0088 
0089     std::memcpy( node_.data(), tmp, node_.size() );
0090     node_[ 0 ] |= 0x01; // mark as multicast
0091 
0092     // generate a pseudorandom 14 bit clock sequence
0093 
0094     state_.clock_seq = static_cast<std::uint16_t>( tmp[ 2 ] & 0x3FFF );
0095 }
0096 
0097 inline time_generator_v1::time_generator_v1( uuid::node_type const& node, state_type const& state ) noexcept: node_( node ), state_( state )
0098 {
0099 }
0100 
0101 inline time_generator_v1::time_generator_v1( uuid::node_type const& node, std::atomic<state_type>& state ) noexcept: node_( node ), ps_( &state )
0102 {
0103 }
0104 
0105 // get_new_state
0106 
0107 inline time_generator_v1::state_type time_generator_v1::get_new_state( state_type const& oldst ) noexcept
0108 {
0109     state_type newst( oldst );
0110 
0111     std::uint64_t timestamp = uuid_clock::now().time_since_epoch().count();
0112 
0113     if( timestamp <= newst.timestamp )
0114     {
0115         newst.clock_seq = ( newst.clock_seq + 1 ) & 0x3FFF;
0116     }
0117 
0118     newst.timestamp = timestamp;
0119 
0120     return newst;
0121 }
0122 
0123 // operator()
0124 
0125 inline time_generator_v1::result_type time_generator_v1::operator()() noexcept
0126 {
0127     if( ps_ )
0128     {
0129         auto oldst = ps_->load( std::memory_order_relaxed );
0130 
0131         for( ;; )
0132         {
0133             auto newst = get_new_state( oldst );
0134 
0135             if( ps_->compare_exchange_strong( oldst, newst, std::memory_order_relaxed, std::memory_order_relaxed ) )
0136             {
0137                 state_ = newst;
0138                 break;
0139             }
0140         }
0141     }
0142     else
0143     {
0144         state_ = get_new_state( state_ );
0145     }
0146 
0147     uuid result;
0148 
0149     std::uint32_t time_low = static_cast< std::uint32_t >( state_.timestamp );
0150 
0151     detail::store_big_u32( result.data + 0, time_low );
0152 
0153     std::uint16_t time_mid = static_cast< std::uint16_t >( state_.timestamp >> 32 );
0154 
0155     detail::store_big_u16( result.data + 4, time_mid );
0156 
0157     std::uint16_t time_hi_and_version = static_cast< std::uint16_t >( state_.timestamp >> 48 ) | 0x1000;
0158 
0159     detail::store_big_u16( result.data + 6, time_hi_and_version );
0160 
0161     detail::store_big_u16( result.data + 8, state_.clock_seq | 0x8000 );
0162 
0163     std::memcpy( result.data + 10, node_.data(), 6 );
0164 
0165     return result;
0166 }
0167 
0168 }} // namespace boost::uuids
0169 
0170 #endif // BOOST_UUID_TIME_GENERATOR_V1_HPP_INCLUDED