GEODE-2408: Refactor CacheableDate with C++11 standards.
Project: http://git-wip-us.apache.org/repos/asf/geode-native/repo Commit: http://git-wip-us.apache.org/repos/asf/geode-native/commit/1d16b3be Tree: http://git-wip-us.apache.org/repos/asf/geode-native/tree/1d16b3be Diff: http://git-wip-us.apache.org/repos/asf/geode-native/diff/1d16b3be Branch: refs/heads/develop Commit: 1d16b3be249693b7bd5bf4422445a0635c9d1379 Parents: 24cbfd3 Author: Jacob Barrett <[email protected]> Authored: Mon Dec 5 17:52:31 2016 -0800 Committer: Jacob Barrett <[email protected]> Committed: Mon Feb 13 13:41:41 2017 -0800 ---------------------------------------------------------------------- src/cppcache/include/gfcpp/CacheableDate.hpp | 184 ++++++++++++++++------ src/cppcache/include/gfcpp/gfcpp_globals.hpp | 10 ++ src/cppcache/src/CacheableDate.cpp | 143 +++++++++-------- 3 files changed, 224 insertions(+), 113 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/geode-native/blob/1d16b3be/src/cppcache/include/gfcpp/CacheableDate.hpp ---------------------------------------------------------------------- diff --git a/src/cppcache/include/gfcpp/CacheableDate.hpp b/src/cppcache/include/gfcpp/CacheableDate.hpp index 0686550..5b465ee 100644 --- a/src/cppcache/include/gfcpp/CacheableDate.hpp +++ b/src/cppcache/include/gfcpp/CacheableDate.hpp @@ -26,15 +26,14 @@ #include "CacheableString.hpp" #include "GeodeTypeIds.hpp" #include "ExceptionTypes.hpp" + +#include <string> +#include <chrono> #include <time.h> #ifdef _WIN32 -#include <WinSock2.h> //for struct timeval -#define GF_LOCALTIME(X, Y) localtime_s(Y, X) +#include <WinSock2.h> // timeval #else -#include <sys/time.h> -#if defined(_LINUX) || defined(_SOLARIS) || defined(_MACOSX) -#define GF_LOCALTIME(X, Y) localtime_r(X, Y) -#endif +#include <sys/time.h> // timeval #endif /** @file @@ -44,108 +43,205 @@ namespace geode { namespace client { /** - * Implement a date object based on system epoch that can serve as a + * Implement a date object based on epoch of January 1, 1970 00:00:00 GMT that can serve as a * distributable key object for caching as well as being a date value. */ -class CPPCACHE_EXPORT CacheableDate : public CacheableKey { - private: - struct timeval m_timevalue; - uint32_t m_hash; +class CPPCACHE_EXPORT CacheableDate + : public CacheableKey +{ + private: + + /** + * Milliseconds since January 1, 1970, 00:00:00 GMT to be consistent with Java Date. + */ + int64_t m_timevalue; + + public: + typedef std::chrono::system_clock clock; + typedef std::chrono::time_point<clock> time_point; + typedef std::chrono::milliseconds duration; - public: /** - *@brief serialize this object + * @brief serialize this object **/ - virtual void toData(DataOutput& output) const; + virtual void toData( DataOutput& output ) const; /** - *@brief deserialize this object + * @brief deserialize this object **/ - virtual Serializable* fromData(DataInput& input); + virtual Serializable* fromData( DataInput& input ); /** * @brief creation function for dates. */ - static Serializable* createDeserializable(); + static Serializable* createDeserializable( ); /** - *@brief Return the classId of the instance being serialized. + * @brief Return the classId of the instance being serialized. * This is used by deserialization to determine what instance * type to create and deserialize into. */ - virtual int32_t classId() const; + virtual int32_t classId( ) const; /** *@brief return the typeId byte of the instance being serialized. * This is used by deserialization to determine what instance * type to create and deserialize into. */ - virtual int8_t typeId() const; + virtual int8_t typeId( ) const; /** @return the size of the object in bytes */ - virtual uint32_t objectSize() const { return sizeof(CacheableDate); } + virtual uint32_t objectSize() const { + return sizeof(CacheableDate); + } /** @return true if this key matches other. */ - virtual bool operator==(const CacheableKey& other) const; + virtual bool operator==( const CacheableKey& other ) const; - /** @return day of the month. */ + /** + * @return day of the month. + * @deprecated Use localtime or similar for calendar conversions. + */ + __DEPRECATED__("Use localtime or similar for calendar conversions.") virtual int day() const; - /** @return month 1(Jan) - 12(Dec) . */ + /** + * @return month 1(Jan) - 12(Dec) . + * @deprecated Use localtime or similar for calendar conversions. + */ + __DEPRECATED__("Use localtime or similar for calendar conversions.") virtual int month() const; - /** @return year, example 1999. */ + /** + * @return year, example 1999. + * @deprecated Use localtime or similar for calendar conversions. + */ + __DEPRECATED__("Use localtime or similar for calendar conversions.") virtual int year() const; - /** @return milliseconds elapsed as per epoch time. */ + /** @return milliseconds elapsed since January 1, 1970, 00:00:00 GMT. */ virtual int64_t milliseconds() const; - /** @return the hashcode for this key. */ + /** + * Returns a hash code value for this object. The result is the exclusive OR + * of the two halves of the primitive long value returned by the milliseconds() + * method. + * + * @return the hashcode for this object. */ virtual uint32_t hashcode() const; + operator time_t() const { return m_timevalue / 1000; } + operator time_point() const { return clock::from_time_t(0) + duration(m_timevalue); } + operator duration() const { return duration(m_timevalue); } + /** * Factory method for creating an instance of CacheableDate */ - static CacheableDatePtr create() { + static CacheableDatePtr create( ) + { return CacheableDatePtr(new CacheableDate()); } - static CacheableDatePtr create(const time_t& value) { + static CacheableDatePtr create( const time_t& value ) + { + return CacheableDatePtr(new CacheableDate(value)); + } + + static CacheableDatePtr create( const time_point& value ) + { return CacheableDatePtr(new CacheableDate(value)); } - static CacheableDatePtr create(const timeval& value) { + static CacheableDatePtr create( const duration& value ) + { return CacheableDatePtr(new CacheableDate(value)); } - virtual CacheableStringPtr toString() const; + /** + * @deprecated Use other standard time types. + */ + __DEPRECATED__("Use other standard time types.") + static CacheableDatePtr create( const timeval& value ) + { + return CacheableDatePtr(new CacheableDate(toDuration(value))); + } + + virtual CacheableStringPtr toString( ) const; /** Destructor */ - virtual ~CacheableDate(); + virtual ~CacheableDate( ); /** used to render as a string for logging. */ - virtual int32_t logString(char* buffer, int32_t maxLength) const; + virtual int32_t logString( char* buffer, int32_t maxLength ) const; + + protected: + + /** Constructor, given a timeval value. + * + * @deprecated Use other constructors. + */ + __DEPRECATED__("Use other standard time types.") + CacheableDate( const timeval& value ); - protected: - /** Constructor, given a timeval value. */ - CacheableDate(const timeval& value); /** Constructor, used for deserialization. */ - CacheableDate(const time_t value = 0); + CacheableDate( const time_t value = 0 ); + + /** + * Construct from std::chrono::time_point<std::chrono::system_clock>. + */ + CacheableDate( const time_point& value ); + + /** + * Construct from std::chrono::seconds since POSIX epoch. + */ + CacheableDate( const duration& value ); + + private: - private: // never implemented. - void operator=(const CacheableDate& other); - CacheableDate(const CacheableDate& other); + void operator=( const CacheableDate& other ); + CacheableDate( const CacheableDate& other ); + + static duration toDuration(const timeval& value) { + return std::chrono::duration_cast<CacheableDate::duration>( + std::chrono::seconds(value.tv_sec) + + std::chrono::microseconds(value.tv_usec)); + } + + public: + friend CacheableKeyPtr createKey( const timeval& value ); + friend CacheablePtr createValue( const timeval& value ); }; -inline CacheableKeyPtr createKey(const timeval& value) { - return CacheableKeyPtr(CacheableDate::create(value)); +/** + * @deprecated Use other standard time types. + */ +__DEPRECATED__("Use other standard time types.") +inline CacheableKeyPtr createKey( const timeval& value ) +{ + return CacheableKeyPtr( CacheableDate::create( CacheableDate::toDuration(value) ) ); +} + +/** + * @deprecated Use other standard time types. + */ +__DEPRECATED__("Use other standard time types.") +inline CacheablePtr createValue( const timeval& value ) +{ + return CacheablePtr( CacheableDate::create( CacheableDate::toDuration(value) ) ); } -inline CacheablePtr createValue(const timeval& value) { - return CacheablePtr(CacheableDate::create(value)); +inline CacheableKeyPtr createKey( const CacheableDate::time_point& value ) +{ + return CacheableKeyPtr( CacheableDate::create( value ) ); } + +inline CacheablePtr createValue( const CacheableDate::time_point& value ) +{ + return CacheablePtr( CacheableDate::create( value ) ); +} + } // namespace client } // namespace geode } // namespace apache http://git-wip-us.apache.org/repos/asf/geode-native/blob/1d16b3be/src/cppcache/include/gfcpp/gfcpp_globals.hpp ---------------------------------------------------------------------- diff --git a/src/cppcache/include/gfcpp/gfcpp_globals.hpp b/src/cppcache/include/gfcpp/gfcpp_globals.hpp index e2ccdaf..712fd59 100644 --- a/src/cppcache/include/gfcpp/gfcpp_globals.hpp +++ b/src/cppcache/include/gfcpp/gfcpp_globals.hpp @@ -92,6 +92,16 @@ #endif +#if defined(__has_cpp_attribute) && __has_cpp_attribute(deprecated) +#define __DEPRECATED__(msg) [[deprecated(msg)]] +#elif defined(__GNUC__) +#define __DEPRECATED__(msg) __attribute__(deprecated(msg)) +#elif defined(_MSC_VER) +#define __DEPRECATED__(msg) __declspec(deprecated(msg)) +#else +#define __DEPRECATED__(msg) +#endif + #ifdef _WIN32 #if WINVER == 0x0500 #endif http://git-wip-us.apache.org/repos/asf/geode-native/blob/1d16b3be/src/cppcache/src/CacheableDate.cpp ---------------------------------------------------------------------- diff --git a/src/cppcache/src/CacheableDate.cpp b/src/cppcache/src/CacheableDate.cpp index 602b5f9..d208b43 100644 --- a/src/cppcache/src/CacheableDate.cpp +++ b/src/cppcache/src/CacheableDate.cpp @@ -26,27 +26,27 @@ #include <cwchar> #include <ace/OS.h> +#include <chrono> +#include <time.h> +#ifdef _WIN32 +#include <WinSock2.h> // timeval +#else +#include <sys/time.h> // timeval +#endif + namespace apache { namespace geode { namespace client { +static CacheableDate::time_point posixEpoch = + CacheableDate::clock::from_time_t(0); + void CacheableDate::toData(DataOutput& output) const { - int64_t msec = static_cast<int64_t>(m_timevalue.tv_sec); - msec *= 1000; - msec += (m_timevalue.tv_usec / 1000); - output.writeInt(msec); + output.writeInt(m_timevalue); } Serializable* CacheableDate::fromData(DataInput& input) { - m_hash = 0; - int64_t msec; - input.readInt(&msec); - - // GF_D_ASSERT( sizeof(time_t)!=4 || (msec/1000)==(time_t)(msec/1000) ); - - m_timevalue.tv_sec = static_cast<long>(msec / 1000); - m_timevalue.tv_usec = (static_cast<suseconds_t>(msec % 1000) * 1000); - + input.readInt(&m_timevalue); return this; } @@ -56,90 +56,95 @@ Serializable* CacheableDate::createDeserializable() { int32_t CacheableDate::classId() const { return 0; } -int8_t CacheableDate::typeId() const { return GeodeTypeIds::CacheableDate; } +int8_t CacheableDate::typeId() const { return GemfireTypeIds::CacheableDate; } bool CacheableDate::operator==(const CacheableKey& other) const { - if (other.typeId() != GeodeTypeIds::CacheableDate) { + if (other.typeId() != GemfireTypeIds::CacheableDate) { return false; } const CacheableDate& otherDt = static_cast<const CacheableDate&>(other); - return ((m_timevalue.tv_sec == otherDt.m_timevalue.tv_sec) && - (m_timevalue.tv_usec == otherDt.m_timevalue.tv_usec)); + return m_timevalue == otherDt.m_timevalue; } -int CacheableDate::day() const { - struct tm date = {0}; - time_t sec = m_timevalue.tv_sec; - GF_LOCALTIME(&sec, &date); + +int CacheableDate::day() const +{ + struct tm date = { 0 }; + time_t sec = m_timevalue / 1000; + ACE_OS::localtime_r( &sec, &date ); return date.tm_mday; } -int CacheableDate::month() const { - struct tm date = {0}; - time_t sec = m_timevalue.tv_sec; - GF_LOCALTIME(&sec, &date); - return date.tm_mon + 1; +int CacheableDate::month() const +{ + struct tm date = { 0 }; + time_t sec = m_timevalue / 1000; + ACE_OS::localtime_r( &sec, &date ); + return date.tm_mon + 1; } -int CacheableDate::year() const { - struct tm date = {0}; - time_t sec = m_timevalue.tv_sec; - GF_LOCALTIME(&sec, &date); - return date.tm_year + 1900; +int CacheableDate::year() const +{ + struct tm date = { 0 }; + time_t sec = m_timevalue / 1000; + ACE_OS::localtime_r( &sec, &date ); + return date.tm_year + 1900; } -int64_t CacheableDate::milliseconds() const { - int64_t tmp = 0; - tmp = static_cast<int64_t>(m_timevalue.tv_sec); - tmp *= 1000; - tmp += (m_timevalue.tv_usec / 1000); - return tmp; +int64_t CacheableDate::milliseconds() const +{ + return m_timevalue; } -uint32_t CacheableDate::hashcode() const { - if (m_hash == 0) { - CacheableDate* self = const_cast<CacheableDate*>(this); - int64_t hash = self->milliseconds(); - self->m_hash = static_cast<int>(hash) ^ static_cast<int>(hash >> 32); - } - return m_hash; +uint32_t CacheableDate::hashcode( ) const +{ + return (int) m_timevalue ^ (int) (m_timevalue >> 32); } -CacheableDate::CacheableDate(const timeval& value) : m_hash(0) { - m_timevalue = value; +CacheableDate::CacheableDate( const timeval& value ) +{ + m_timevalue = (((int64_t) value.tv_sec) * 1000) + (value.tv_usec / 1000); } -CacheableDate::CacheableDate(const time_t value) : m_hash(0) { - m_timevalue.tv_sec = static_cast<long>(value); - m_timevalue.tv_usec = 0; +CacheableDate::CacheableDate( const time_t value ) +{ + m_timevalue = ((int64_t) value) * 1000; } -CacheableDate::~CacheableDate() { - m_hash = 0; - m_timevalue.tv_sec = 0; - m_timevalue.tv_usec = 0; +CacheableDate::CacheableDate(const CacheableDate::time_point& value) { + // Set based on time since local system clock epoch plus time since POSIX + // epoch since local system clock epoch to get milliseconds since POSIX epoch. + m_timevalue = + std::chrono::duration_cast<CacheableDate::duration>(value - posixEpoch) + .count(); +} + +CacheableDate::CacheableDate(const CacheableDate::duration& value) { + m_timevalue = value.count(); +} + +CacheableDate::~CacheableDate( ) +{ } CacheableStringPtr CacheableDate::toString() const { char buffer[25]; - struct tm date = {0}; - time_t sec = m_timevalue.tv_sec; - GF_LOCALTIME(&sec, &date); - ACE_OS::snprintf(buffer, 24, "%d/%d/%d %d:%d:%d", date.tm_mon + 1, - date.tm_mday, date.tm_year + 1900, date.tm_hour, date.tm_min, - date.tm_sec); - return CacheableString::create(buffer); -} - -int32_t CacheableDate::logString(char* buffer, int32_t maxLength) const { - struct tm date = {0}; - time_t sec = m_timevalue.tv_sec; - GF_LOCALTIME(&sec, &date); - return ACE_OS::snprintf(buffer, maxLength, - "CacheableDate (mm/dd/yyyy) ( %d/%d/%d )", - date.tm_mon + 1, date.tm_mday, date.tm_year + 1900); + struct tm date = { 0 }; + time_t sec = m_timevalue / 1000; + ACE_OS::localtime_r(&sec, &date); + ACE_OS::snprintf(buffer, 24, "%d/%d/%d %d:%d:%d", date.tm_mon+1, date.tm_mday, date.tm_year+1900, date.tm_hour, date.tm_min, date.tm_sec); + return CacheableString::create( buffer ); } + +int32_t CacheableDate::logString( char* buffer, int32_t maxLength ) const +{ + struct tm date = { 0 }; + time_t sec = m_timevalue / 1000; + ACE_OS::localtime_r(&sec, &date); + return ACE_OS::snprintf( buffer, maxLength, "CacheableDate (mm/dd/yyyy) ( %d/%d/%d )", date.tm_mon+1, date.tm_mday, date.tm_year+1900 ); +} + } // namespace client } // namespace geode } // namespace apache
