001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
038:
039:
040:
041:
042:
043:
044:
045:
046:
047:
048:
049:
050:
051:
052:
053:
054:
055:
056:
057:
058:
059:
060:
061:
062:
063:
064:
065:
066:
067:
068:
069:
070:
071:
072:
073:
074:
075:
076:
077:
078:
079:
080:
081:
082:
083:
084:
085:
086:
087:
088:
089:
090:
091:
092:
093:
094:
095:
096:
097:
098:
099:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:


/*
* This file is part of the Omni C++ framework
*
* Copyright (c) 2016, Zeriph Enterprises, LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of Zeriph, Zeriph Enterprises, LLC, nor the names
* of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ZERIPH AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ZERIPH AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(OMNI_CHRONO_T_HPP)
#define OMNI_CHRONO_T_HPP 1
#include <omni/types/tick_t.hpp>
namespace omni {
namespace chrono {
class monotonic
{
public:
inline static omni::chrono::tick_t tick()
{
#if defined(OMNI_OS_WIN)
#if defined(OMNI_WIN_MONO_TICK_QPC)
omni::chrono::tick_t tmp;
if (m_freq.LowPart == 0) { ::QueryPerformanceFrequency(&m_freq); }
if (::QueryPerformanceCounter(&tmp) == 0) {
std::memset(&tmp, 0, sizeof(OMNI_CLOCK_TICK_T));
OMNI_ERR_FW("An error occurred getting the clock time", omni::clock_exception())
}
return tmp;
#else
return
#if defined(OMNI_WIN_API)
#if defined(OMNI_WIN_MONO_TICK_COUNT)
::GetTickCount()
#elif defined(OMNI_WIN_MONO_TICK_COUNT64)
::GetTickCount64()
#endif
#else
std::clock()
#endif
;
#endif
#elif defined(OMNI_OS_APPLE)
if (m_freq.denom == 0) { ::mach_timebase_info(&m_freq); }
return ::mach_absolute_time();
#else
omni::chrono::tick_t tmp;
if (m_freq.tv_nsec == 0) {
// CLOCK_MONOTONIC by default but can be configured for CLOCK_REALTIME where applicable (like QNX)
if (::clock_getres(OMNI_CLOCK_GETRES_CID_FW, &m_freq) != 0) {
std::memset(&tmp, 0, sizeof(OMNI_CLOCK_TICK_T));
OMNI_ERRV_FW("An error occurred getting the clock resolution: ", std::strerror(errno), omni::clock_exception(errno))
}
}
if (::clock_gettime(CLOCK_MONOTONIC, &tmp) != 0) {
std::memset(&tmp, 0, sizeof(OMNI_CLOCK_TICK_T));
OMNI_ERRV_FW("An error occurred getting the clock time: ", std::strerror(errno), omni::clock_exception(errno))
}
return tmp;
#endif
}
inline static double elapsed_us(omni::chrono::tick_t init, omni::chrono::tick_t end)
{
#if defined(OMNI_OS_APPLE)
return (static_cast<double>((end - init)) * static_cast<double>(m_freq.numer)) / static_cast<double>(m_freq.denom * 1000);
#else
#if defined(OMNI_OS_WIN)
#if defined(OMNI_WIN_MONO_TICK_QPC)
return (static_cast<double>(((end.QuadPart - init.QuadPart) * 1000000)) / static_cast<double>(m_freq.QuadPart));
#else
return static_cast<double>(end - init);
#endif
#else
return ((end.tv_sec - init.tv_sec) * 1000000) + (static_cast<double>((end.tv_nsec - init.tv_nsec)) / 1000);
#endif
#endif
}
inline static double elapsed_ms(omni::chrono::tick_t init, omni::chrono::tick_t end)
{
return (omni::chrono::monotonic::elapsed_us(init, end) / 1000);
}
inline static double elapsed_s(omni::chrono::tick_t init, omni::chrono::tick_t end)
{
return (omni::chrono::monotonic::elapsed_us(init, end) / 1000000);
}
inline static double elapsed_us(omni::chrono::tick_t init)
{
return omni::chrono::monotonic::elapsed_us(init, omni::chrono::monotonic::tick());
}
inline static double elapsed_ms(omni::chrono::tick_t init)
{
return omni::chrono::monotonic::elapsed_ms(init, omni::chrono::monotonic::tick());
}
inline static double elapsed_s(omni::chrono::tick_t init)
{
return omni::chrono::monotonic::elapsed_s(init, omni::chrono::monotonic::tick());
}
inline static omni::chrono::freq_t frequency()
{
#if defined(OMNI_OS_WIN) && !defined(OMNI_WIN_MONO_TICK_QPC)
return 0;
#else
return m_freq;
#endif
}
private:
monotonic(); // = delete;
monotonic(const monotonic& cp); // = delete;
monotonic& operator=(const monotonic& cp); // = delete;
static omni::chrono::freq_t m_freq;
};
inline omni::chrono::tick_t monotonic_tick()
{
return omni::chrono::monotonic::tick();
}
inline bool equal(const omni::chrono::tick_t& t1, const omni::chrono::tick_t& t2)
{
/* this is an inline bool so as not to inadvertently override the equality operator, the user
has to expressly call the function instead of an implicit function call made by compiler where
a call to t1 == t2 is made */
return
#if defined(OMNI_OS_APPLE)
(t1 == t2)
#elif defined(OMNI_OS_WIN)
#if defined(OMNI_WIN_MONO_TICK_QPC)
(t1.QuadPart == t2.QuadPart)
#else
(t1 == t2)
#endif
#else
(t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec)
#endif
;
}
// for double precision use omni::chrono::monotonic::elapsed_us
inline std::size_t elapsed_us(omni::chrono::tick_t init, omni::chrono::tick_t end)
{
return static_cast<std::size_t>(omni::chrono::monotonic::elapsed_us(init, end));
}
// for double precision use omni::chrono::monotonic::elapsed_us
inline std::size_t elapsed_us(omni::chrono::tick_t init)
{
return static_cast<std::size_t>(omni::chrono::monotonic::elapsed_us(init));
}
// for double precision use omni::chrono::monotonic::elapsed_ms
inline std::size_t elapsed_ms(omni::chrono::tick_t init, omni::chrono::tick_t end)
{
return static_cast<std::size_t>(omni::chrono::monotonic::elapsed_ms(init, end));
}
// for double precision use omni::chrono::monotonic::elapsed_ms
inline std::size_t elapsed_ms(omni::chrono::tick_t init)
{
return static_cast<std::size_t>(omni::chrono::monotonic::elapsed_ms(init));
}
// for double precision use omni::chrono::monotonic::elapsed_s
inline std::size_t elapsed_s(omni::chrono::tick_t init, omni::chrono::tick_t end)
{
return static_cast<std::size_t>(omni::chrono::monotonic::elapsed_s(init, end));
}
// for double precision use omni::chrono::monotonic::elapsed_s
inline std::size_t elapsed_s(omni::chrono::tick_t init)
{
return static_cast<std::size_t>(omni::chrono::monotonic::elapsed_s(init));
}
}
}
#endif // OMNI_CHRONO_T_HPP