// -*- C++ -*-
//=============================================================================
/**
* @file Time_Value.h
*
* @author Douglas C. Schmidt
*/
//=============================================================================
#ifndef ACE_TIME_VALUE_H
#define ACE_TIME_VALUE_H
#include /**/ "ace/pre.h"
#include /**/ "ace/ACE_export.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
#include "ace/os_include/os_time.h"
#include "ace/Truncate.h"
#include
#include
// Define some helpful constants.
// Not type-safe, and signed. For backward compatibility.
#define ACE_ONE_SECOND_IN_MSECS 1000L
suseconds_t const ACE_ONE_SECOND_IN_USECS = 1000000;
#define ACE_ONE_SECOND_IN_NSECS 1000000000L
// needed for ACE_UINT64
#include "ace/Basic_Types.h"
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
/**
* @class ACE_Time_Value
*
* @brief Operations on "timeval" structures, which express time in
* seconds (secs) and microseconds (usecs).
*
* This class centralizes all the time related processing in
* ACE. These time values are typically used in conjunction with OS
* mechanisms like or other calls that may have
* *their own* implementation-specific maximum time representations.
* Its primary use is in time computations such as those used by the
* dynamic subpriority strategies in the ACE_Dynamic_Message_Queue
* class.
*/
static const ACE_Time_Value max_time;
/// Default Constructor.
ACE_Time_Value ();
/// Constructor.
explicit ACE_Time_Value (time_t sec, suseconds_t usec = 0);
// = Methods for converting to/from various time formats.
/// Construct the ACE_Time_Value from a timeval.
explicit ACE_Time_Value (const struct timeval &t);
/// Construct the ACE_Time_Value object from a timespec_t.
explicit ACE_Time_Value (const timespec_t &t);
ACE_Time_Value (const ACE_Time_Value&) = default;
ACE_Time_Value (ACE_Time_Value&&) = default;
/// Construct the ACE_Time_Value object from a chrono duration.
template< class Rep, class Period >
explicit ACE_Time_Value (const std::chrono::duration& duration)
{
this->set (duration);
}
/// Destructor
virtual ~ACE_Time_Value () = default;
/// Declare the dynamic allocation hooks.
ACE_ALLOC_HOOK_DECLARE;
# if defined (ACE_WIN32)
/// Construct the ACE_Time_Value object from a Win32 FILETIME
explicit ACE_Time_Value (const FILETIME &ft);
# endif /* ACE_WIN32 */
/// Initializes the ACE_Time_Value from seconds and useconds.
void set (time_t sec, suseconds_t usec);
/// Initializes the ACE_Time_Value from a double, which is assumed to be
/// in second format, with any remainder treated as microseconds.
void set (double d);
/// Initializes the ACE_Time_Value from a timeval.
void set (const timeval &t);
/// Initializes the ACE_Time_Value object from a timespec_t.
void set (const timespec_t &t);
# if defined (ACE_WIN32)
/// Initializes the ACE_Time_Value object from a Win32 FILETIME.
void set (const FILETIME &ft);
# endif /* ACE_WIN32 */
/// Initializes the ACE_Time_Value object from a std::duration.
template< class Rep, class Period >
void set (const std::chrono::duration& duration)
{
std::chrono::seconds const s {
std::chrono::duration_cast (duration)};
std::chrono::microseconds const usec {
std::chrono::duration_cast(
duration % std::chrono::seconds (1))};
this->set (s.count (), ACE_Utils::truncate_cast(usec.count ()));
}
/// Converts from ACE_Time_Value format into milliseconds format.
/**
* @return Sum of second field (in milliseconds) and microsecond field
* (in milliseconds). Note that this method can overflow if
* the second and microsecond field values are large, so use
* the msec (ACE_UINT64 &ms) method instead.
*
* @note The semantics of this method differs from the sec() and
* usec() methods. There is no analogous "millisecond"
* component in an ACE_Time_Value.
*/
unsigned long msec () const;
/// Converts from ACE_Time_Value format into milliseconds format.
/**
* @return Sum of second field (in milliseconds) and microsecond field
* (in milliseconds).
*
* @note The semantics of this method differs from the sec() and
* usec() methods. There is no analogous "millisecond"
* component in an ACE_Time_Value.
*/
ACE_UINT64 get_msec () const;
/// Converts from ACE_Time_Value format into milliseconds format.
/**
* @return Sum of second field (in milliseconds) and microsecond field
* (in milliseconds) and return them via the @param ms parameter.
*
* @note The semantics of this method differs from the sec() and
* usec() methods. There is no analogous "millisecond"
* component in an ACE_Time_Value.
*
* @deprecated Use get_msec() instead.
*/
void msec (ACE_UINT64 &ms) const;
/// Converts from ACE_Time_Value format into milliseconds format.
/**
* @return Sum of second field (in milliseconds) and microsecond field
* (in milliseconds) and return them via the @param ms parameter.
*
* @note The semantics of this method differs from the sec() and
* usec() methods. There is no analogous "millisecond"
* component in an ACE_Time_Value.
*
* @deprecated Use get_msec() instead.
*/
void msec (ACE_UINT64 &ms) /* const */;
/// Converts from milli-seconds format into ACE_Time_Value format.
/**
* @note The semantics of this method differs from the sec() and
* usec() methods. There is no analogous "millisecond"
* component in an ACE_Time_Value.
*/
void set_msec (const ACE_UINT64 &ms);
/// Converts from milli-seconds format into ACE_Time_Value format.
/**
* @note The semantics of this method differs from the sec() and
* usec() methods. There is no analogous "millisecond"
* component in an ACE_Time_Value.
*/
void msec (long);
/// Converts from milli-seconds format into ACE_Time_Value format.
/**
* @note The semantics of this method differs from the sec() and
* usec() methods. There is no analogous "millisecond"
* component in an ACE_Time_Value.
*/
void msec (int); // converted to long then calls above.
/// Returns the value of the object as a timespec_t.
operator timespec_t () const;
/// Returns the value of the object as a timeval.
operator timeval () const;
/// Returns a pointer to the object as a timeval.
operator const timeval *() const;
# if defined (ACE_WIN32)
/// Returns the value of the object as a Win32 FILETIME.
operator FILETIME () const;
# endif /* ACE_WIN32 */
// = The following are accessor/mutator methods.
/// Get seconds.
/**
* @return The second field/component of this ACE_Time_Value.
*
* @note The semantics of this method differs from the msec()
* method.
*/
time_t sec () const;
/// Set seconds.
void sec (time_t sec);
/// Get microseconds.
/**
* @return The microsecond field/component of this ACE_Time_Value.
*
* @note The semantics of this method differs from the msec()
* method.
*/
suseconds_t usec () const;
/// Set microseconds.
void usec (suseconds_t usec);
/**
* @return Sum of second field (in microseconds) and microsecond field
* and return them via the @param usec parameter.
*/
void to_usec (ACE_UINT64 &usec) const;
// = The following arithmetic methods operate on ACE_Time_Value's.
/// Add @a tv to this.
ACE_Time_Value &operator += (const ACE_Time_Value &tv);
/// Add @a tv to this.
ACE_Time_Value &operator += (time_t tv);
/// Assign @a tv to this
ACE_Time_Value &operator = (const ACE_Time_Value &) = default;
ACE_Time_Value &operator = (ACE_Time_Value &&) = default;
/// Assign @a tv to this
ACE_Time_Value &operator = (time_t tv);
/// Subtract @a tv to this.
ACE_Time_Value &operator -= (const ACE_Time_Value &tv);
/// Subtract @a tv to this.
ACE_Time_Value &operator -= (time_t tv);
/// Add @a std::duration to this.
template< class Rep, class Period >
ACE_Time_Value &operator += (const std::chrono::duration& duration)
{
const ACE_Time_Value tv (duration);
this->sec (this->sec () + tv.sec ());
this->usec (this->usec () + tv.usec ());
this->normalize ();
return *this;
}
/// Assign @a std::duration to this
template< class Rep, class Period >
ACE_Time_Value &operator = (const std::chrono::duration& duration)
{
this->set (duration);
return *this;
}
/// Subtract @a std::duration to this.
template< class Rep, class Period >
ACE_Time_Value &operator -= (const std::chrono::duration& duration)
{
const ACE_Time_Value tv (duration);
this->sec (this->sec () - tv.sec ());
this->usec (this->usec () - tv.usec ());
this->normalize ();
return *this;
}
/**
\brief Multiply the time value by the @a d factor.
\note The result of the operator is valid for results from range
< (ACE_INT32_MIN, -999999), (ACE_INT32_MAX, 999999) >. Result
outside this range are saturated to a limit.
*/
ACE_Time_Value &operator *= (double d);
/// Increment microseconds as postfix.
/**
* @note The only reason this is here is to allow the use of ACE_Atomic_Op
* with ACE_Time_Value.
*/
ACE_Time_Value operator++ (int);
/// Increment microseconds as prefix.
/**
* @note The only reason this is here is to allow the use of ACE_Atomic_Op
* with ACE_Time_Value.
*/
ACE_Time_Value &operator++ ();
/// Decrement microseconds as postfix.
/**
* @note The only reason this is here is to allow the use of ACE_Atomic_Op
* with ACE_Time_Value.
*/
ACE_Time_Value operator-- (int);
/// Decrement microseconds as prefix.
/**
* @note The only reason this is here is to allow the use of ACE_Atomic_Op
* with ACE_Time_Value.
*/
ACE_Time_Value &operator-- ();
/// Adds two ACE_Time_Value objects together, returns the sum.
friend ACE_Export ACE_Time_Value operator + (const ACE_Time_Value &tv1,
const ACE_Time_Value &tv2);
/// Subtracts two ACE_Time_Value objects, returns the difference.
friend ACE_Export ACE_Time_Value operator - (const ACE_Time_Value &tv1,
const ACE_Time_Value &tv2);
/// True if @a tv1 < @a tv2.
friend ACE_Export bool operator < (const ACE_Time_Value &tv1,
const ACE_Time_Value &tv2);
/// True if @a tv1 > @a tv2.
friend ACE_Export bool operator > (const ACE_Time_Value &tv1,
const ACE_Time_Value &tv2);
/// True if @a tv1 <= @a tv2.
friend ACE_Export bool operator <= (const ACE_Time_Value &tv1,
const ACE_Time_Value &tv2);
/// True if @a tv1 >= @a tv2.
friend ACE_Export bool operator >= (const ACE_Time_Value &tv1,
const ACE_Time_Value &tv2);
/// True if @a tv1 == @a tv2.
friend ACE_Export bool operator == (const ACE_Time_Value &tv1,
const ACE_Time_Value &tv2);
/// True if @a tv1 != @a tv2.
friend ACE_Export bool operator != (const ACE_Time_Value &tv1,
const ACE_Time_Value &tv2);
//@{
/// Multiplies the time value by @a d
friend ACE_Export ACE_Time_Value operator * (double d,
const ACE_Time_Value &tv);
friend ACE_Export ACE_Time_Value operator * (const ACE_Time_Value &tv,
double d);
//@}
/// Get current time of day.
/**
* @return Time value representing current time of day.
*
* @note This method is overloaded in the time policy based template
* instantiations derived from this class. Allows for time policy
* aware time values.
*/
virtual ACE_Time_Value now () const;
/// Converts absolute time value to time value relative to current time of day.
/**
* @return Relative time value.
*
* @note This method is overloaded in the time policy based template
* instantiations derived from this class. Allows for time policy
* aware time values.
* The developer is responsible for making sure this is an absolute
* time value compatible with the active time policy (which is system
* time for the base class).
*/
virtual ACE_Time_Value to_relative_time () const;
/// Converts relative time value to absolute time value based on current time of day.
/**
* @return Absolute time value.
*
* @note This method is overloaded in the time policy based template
* instantiations derived from this class. Allows for time policy
* aware time values.
* The developer is responsible for making sure this is a relative
* time value. Current time of day is determined based on time policy
* (which is system time for the base class).
*/
virtual ACE_Time_Value to_absolute_time () const;
/// Duplicates this time value (incl. time policy).
/**
* @return Dynamically allocated time value copy.
*
* @note The caller is responsible for freeing the copy when it's not needed
* anymore.
*/
virtual ACE_Time_Value * duplicate () const;
/// Dump is a no-op.
/**
* The dump() method is a no-op. It's here for backwards compatibility
* only, but does not dump anything. Invoking logging methods here
* violates layering restrictions in ACE because this class is part
* of the OS layer and @c ACE_Log_Msg is at a higher level.
*/
void dump () const;
# if defined (ACE_WIN32)
/// Const time difference between FILETIME and POSIX time.
static const DWORDLONG FILETIME_to_timval_skew;
# endif /* ACE_WIN32 */
private:
/// Put the timevalue into a canonical form.
void normalize (bool saturate = false);
/// Store the values as a timeval.
#if defined (ACE_HAS_TIME_T_LONG_MISMATCH)
// Windows' timeval is non-conformant, so swap in a struct that conforms
// to the proper data types to represent the entire time range that this
// class's API can accept.
// Also, since this class can supply a pointer to a timeval that things
// like select() expect, we need the OS-defined one as well. To make this
// available, use a real timeval called ext_tv_ and set it up when needed.
// Since this is most often for relative times that don't approach 32 bits
// in size, reducing a time_t to fit should be no problem.
struct {
time_t tv_sec;
suseconds_t tv_usec;
} tv_;
timeval ext_tv_;
#else
timeval tv_;
#endif /* ACE_HAS_TIME_T_LONG_MISMATCH */
};
extern ACE_Export std::ostream &operator<<(std::ostream &o, const ACE_Time_Value &v );
ACE_END_VERSIONED_NAMESPACE_DECL
// Additional chrono operators.
namespace std
{
namespace chrono
{
/**
* @name Streaming ACE_Time_Value to chrono
*
* Streaming an ACE_Time_Value into one of the chrono types (nanoseconds,
* microseconds, milliseconds, seconds, minutes, or hours).
*
*/
//@{
ACE_Export nanoseconds& operator <<(nanoseconds &ns, ACE_Time_Value const &tv);
ACE_Export microseconds& operator <<(microseconds &us, ACE_Time_Value const &tv);
ACE_Export milliseconds& operator <<(milliseconds &ms, ACE_Time_Value const &tv);
ACE_Export seconds& operator <<(seconds &s, ACE_Time_Value const &tv);
ACE_Export minutes& operator <<(minutes &m, ACE_Time_Value const &tv);
ACE_Export hours& operator <<(hours &h, ACE_Time_Value const &tv);
//@}
/**
* @name Adding ACE_Time_Value to chrono
*
* Adding an ACE_Time_Value to one of the chrono types (nanoseconds,
* microseconds, milliseconds, seconds, minutes, or hours).
*
*/
//@{
ACE_Export nanoseconds& operator +=(nanoseconds &ns, ACE_Time_Value const &tv);
ACE_Export microseconds& operator +=(microseconds &us, ACE_Time_Value const &tv);
ACE_Export milliseconds& operator +=(milliseconds &ms, ACE_Time_Value const &tv);
ACE_Export seconds& operator +=(seconds &s, ACE_Time_Value const &tv);
ACE_Export minutes& operator +=(minutes &m, ACE_Time_Value const &tv);
ACE_Export hours& operator +=(hours &h, ACE_Time_Value const &tv);
//@}
/**
* @name Substracting ACE_Time_Value from chrono
*
* Substracting an ACE_Time_Value from one of the chrono types (nanoseconds,
* microseconds, milliseconds, seconds, minutes, or hours).
*
*/
//@{
ACE_Export nanoseconds& operator -=(nanoseconds &ns, ACE_Time_Value const &tv);
ACE_Export microseconds& operator -=(microseconds &us, ACE_Time_Value const &tv);
ACE_Export milliseconds& operator -=(milliseconds &ms, ACE_Time_Value const &tv);
ACE_Export seconds& operator -=(seconds &s, ACE_Time_Value const &tv);
ACE_Export minutes& operator -=(minutes &m, ACE_Time_Value const &tv);
ACE_Export hours& operator -=(hours &h, ACE_Time_Value const &tv);
//@}
}
}
#if defined (__ACE_INLINE__)
#include "ace/Time_Value.inl"
#endif /* __ACE_INLINE__ */
#if defined (__MINGW32__)
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
// The MingW linker has problems with the exported statics
// zero and max_time with these two statics the linker will be able to
// resolve the static exported symbols.
static const ACE_Time_Value& __zero_time = ACE_Time_Value::zero;
static const ACE_Time_Value& __max_time = ACE_Time_Value::max_time;
ACE_END_VERSIONED_NAMESPACE_DECL
#endif /* __MINGW32__ */
#include /**/ "ace/post.h"
#endif /* ACE_TIME_VALUE_H */