本计时器精确到微秒。目前版本V1.0.0
Download:Clock-V1.0.0.7z
目录关系:
文件:Clock/Clock
#pragma once /** * Clock - High precision clock calculation --C++-- * This file is under GNU General Public Licence, * free to copy or edit. * * * Copyright (c) 2012 * Adam Basfop Cavendish * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Adam Basfop Cavendish makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * * * @version V1.0.0, last edited on 09. 13, 2012. * @file Clock/Clock * @brief This is a header for High precision Clock * calculating the time elapse between two * period of time. * @info Any project compiled with this file should * be at least compiled with 2011 c++ standard, * for example: g++ -std=c++0x test.cpp */ #include "Core/Clock.hpp" #include "Core/Clock.tcc"
文件:Clock/Core/Clock.hpp
#pragma once
#include <chrono>
#include <ratio>
#include <string>
#include <iostream>
#include <iomanip>
#include <stdexcept>
template <typename clock = std::chrono::high_resolution_clock>
class Clock
{
typedef std::chrono::duration<int, std::ratio<3600*24>> chrono_days;
public: // functions
// constructors
/**
* @brief Default constructor - creating a empty Clock,
* initialized at zero
*/
Clock() : start_time(nullptr) {}
/**
* @brief Constructs a Clock at a initialized time with a time_point
* initialized at tp minus the clock's epoch time
*/
Clock(typename clock::time_point tp) : start_time(nullptr) {
total_time += tp;
}// constructor(time_point)
/**
* @brief Constructs a Clock at a initialized time with a duration
* initialized at duration.
*/
template <typename Duration>
Clock(Duration du) : start_time(nullptr) {
total_time += du;
}// constructor(duration)
/**
* @brief Start calculating the time, until pause() is called.
*/
void start() {
if(start_time != nullptr)
throw std::runtime_error("Clock Already started!");
start_time = new typename clock::time_point(clock::now());
}//start()
/**
* @brief Pause the time, and the total_time will be
* increased by paused_time minus started_time
*/
void pause() {
typename clock::time_point pause_time(clock::now());
if(start_time == nullptr)
throw std::runtime_error("Clock has not been started!");
total_time += pause_time - *start_time;
delete start_time;
start_time = nullptr;
}//pause()
/**
* @brief Clear the Clock, and the time of the Clock
* will be set to zero
*/
void clear() {
if(start_time != nullptr) {
delete start_time;
start_time = nullptr;
}//if
std::chrono::time_point<clock> tp;
total_time = tp;
}//clear()
/**
* @brief add time to the Clock by duration du
* @param Duration du, the duration to be increased
*/
template <typename Duration>
void addTime(const Duration &du) {
total_time += du;
}//addTime(Duration)
/**
* @brief reduce time from the Clock by duration du
* @param Duration du, the duration to be reduced from the Clock
*/
template <typename Duration>
void reduceTime(const Duration &du) {
total_time -= du;
}//reduceTime(Duration)
/**
* @brief make up a time_point according to the time
*/
typename clock::time_point makeTimePoint(
int year,
int month,
int day,
int hour = 0,
int minute = 0,
int second = 0,
int millisecond = 0,
int microsecond = 0
);
/**
* @brief Convert the Clock to system time
* print example: Thu Jan 1 08:00:00 1970
*/
std::string toString(const typename clock::time_point &start_time_point) {
std::time_t t = clock::to_time_t(
start_time_point + total_time.time_since_epoch()
); // convert to system time
std::string ts = ctime(&t); // convert to calendar time
ts.resize(ts.size() - 1); // skip trailing newline
return ts;
}//toString()
/**
* @brief print the Clock's counting time
* @param os -- The ostream for print, default is std::cout
* @param option -- The option for printing.
* Using DAY, HOUR, MIN, SEC, MILLI, MICRO, NANO
* for printing day, hour, minute, second,
* millisecond, microsecond, nanosecond part of
* the information.
* Using '|' to print multiple parts.
* default is to print all of them.
*
* @param hint -- The hint message for printing, default: "Clock: "
* @example print example: "Clock: 00 Day(s) 00 Hours(s) 00 Min(s) \
* 00 Second(s) 000 Milli(s) 000 Micro(s) 000 Nano(s)"
*/
void print(
std::ostream &os = std::cout,
const int option = (DAY | HOUR | MIN | SEC | MILLI | MICRO | NANO),
const std::string &hint = "Clock: "
);
/**
* @brief execute a file and calculate the elapsed time of the execution
* @param cmdline -- the command line, example: execute_file("a.out 100 99 98");
*/
int execute_file(const char *cmdline);
int execute_file(const std::string &cmdline);
/**
* @brief Create cmdline using argc and argv starting at argc = argc_start.
* This function is written for those who want to execute a file
* that is inputed by arguments.
*/
const std::string createCmdline(int argc, char *argv[], int argc_start = 1);
// geters and seters
/**
* @brief get the total_time time_point
*/
const typename clock::time_point getTotalTime() { return total_time; }
/**
* @brief get the information of the Clock
*/
const chrono_days getDays() {
return std::chrono::duration_cast<chrono_days>
(total_time.time_since_epoch());
}//getDays()
const std::chrono::hours getHours() {
return std::chrono::duration_cast<std::chrono::hours>
(total_time.time_since_epoch() % chrono_days(1));
}//getHours()
const std::chrono::minutes getMinutes() {
return std::chrono::duration_cast<std::chrono::minutes>
(total_time.time_since_epoch() % std::chrono::hours(1));
}//getMinutes()
const std::chrono::seconds getSeconds() {
return std::chrono::duration_cast<std::chrono::seconds>
(total_time.time_since_epoch() % std::chrono::minutes(1));
}//getSeconds()
const std::chrono::milliseconds getMilliseconds() {
return std::chrono::duration_cast<std::chrono::milliseconds>
(total_time.time_since_epoch() % std::chrono::seconds(1));
}//getMilliseconds()
const std::chrono::microseconds getMicroseconds() {
return std::chrono::duration_cast<std::chrono::microseconds>
(total_time.time_since_epoch() % std::chrono::milliseconds(1));
}//getMicroseconds()
const std::chrono::nanoseconds getNanoseconds() {
return std::chrono::duration_cast<std::chrono::nanoseconds>
(total_time.time_since_epoch() % std::chrono::microseconds(1));
}//getNanoseconds()
// destructors
~Clock() { if(start_time != nullptr) delete start_time; }
private: // functions
/**
* @brief to check whether the cmdline str has space ' ' or '\t' in it
* supports the '\' to merge two lines
*/
bool hasSpace(const char *str);
#if defined (WINDOWS) || (__WINDOWS__) || (_WIN64) || (_WIN32) || \
(WIN64) || (WIN32)
int windows_execute(const char *cmdline);
#elif defined (__linux) || (__unix) || (__posix) || \
(__linux__) || (__unix__) || (__posix__)
int posix_execute(const char *cmdline);
#endif // OS-Check
public: // variables
/**
* @brief The static value for option in print,
* use them to print the specific part.
* @param ALL = DAY | HOUR | MIN | SEC | MILLI | MICRO | NANO
*/
enum {
DAY = (1 << 6),
HOUR = (1 << 5),
MIN = (1 << 4),
SEC = (1 << 3),
MILLI = (1 << 2),
MICRO = (1 << 1),
NANO = (1 << 0),
ALL = (0x3F),
COMMON = (0x0E),
}; // enum
private: // variables
typename clock::time_point total_time;
typename clock::time_point *start_time;
};//class Clock
文件:Clock/Core/Clock.tcc
#include "Clock.hpp"
#include <iostream>
#include <chrono>
#include <string>
#include <cstring>
#include <stdexcept>
#include <ctime>
#if defined (WINDOWS) || defined (__WINDOWS__) || defined (_WIN64) || defined (_WIN32) || \
defined (WIN64) || defined (WIN32)
#include <windows.h>
#elif defined (__linux) || defined (__unix) || defined (__posix) || \
defined (__linux__) || defined (__unix__) || defined (__posix__)
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#endif // OS-Check
template <typename clock>
typename clock::time_point Clock<clock>::makeTimePoint(
int year,
int month,
int day,
int hour,
int minute,
int second,
int millisecond,
int microsecond
)
{
struct std::tm t;
t.tm_sec = second; // second of minute (0 .. 59 and 60 for leap seconds)
t.tm_min = minute; // minute of hour (0 .. 59)
t.tm_hour = hour; // hour of day (0 .. 23)
t.tm_mday = day; // day of month (0 .. 31)
t.tm_mon = month-1; // month of year (0 .. 11)
t.tm_year = year-1900; // year since 1900
t.tm_isdst = -1; // determine whether daylight saving time
std::time_t tt = std::mktime(&t);
if(tt == -1)
throw std::domain_error("Invalid time, time_point cannot be made");
if(millisecond < 0 || millisecond > 999 ||
microsecond < 0 || microsecond > 999)
// nanosecond < 0 || nanosecond > 999)
throw std::domain_error("Invalid time, time_point cannot be made");
typename clock::time_point ret_tp = clock::from_time_t(tt);
std::chrono::milliseconds milli(millisecond);
std::chrono::microseconds micro(microsecond);
// std::chrono::nanoseconds nano(nanosecond);
ret_tp += milli;
ret_tp += micro;
// ret_tp += nano;
return ret_tp;
}//makeTimePoint(year, month, day, hour, minute, second, millisecond, microsecond)
template <typename clock>
void Clock<clock>::print(
std::ostream &os,
const int option,
const std::string &hint)
{
if(option <= 0)
return;
os << hint << std::setfill('0');
if((option & DAY) > 0)
os << std::setw(2) << getDays().count() << " Day(s) ";
if((option & HOUR) > 0)
os << std::setw(2) << getHours().count() << " Hours(s) ";
if((option & MIN) > 0)
os << std::setw(2) << getMinutes().count() << " Min(s) ";
if((option & SEC) > 0)
os << std::setw(2) << getSeconds().count() << " Second(s) ";
if((option & MILLI) > 0)
os << std::setw(3) << getMilliseconds().count() << " Milli(s) ";
if((option & MICRO) > 0)
os << std::setw(3) << getMicroseconds().count() << " Micro(s) ";
if((option & NANO) > 0)
os << std::setw(3) << getNanoseconds().count() << " Nano(s) ";
os << std::endl;
}//print(os, option, hint)
template <typename clock>
int Clock<clock>::execute_file(const char *cmdline)
{
#if defined (WINDOWS) || defined (__WINDOWS__) || defined (_WIN64) || defined (_WIN32) || \
defined (WIN64) || defined (WIN32)
return windows_execute(cmdline);
#elif defined (__linux) || defined (__unix) || defined (__posix) || \
defined (__linux__) || defined (__unix__) || defined (__posix__)
return posix_execute(cmdline);
#endif // OS-Check
}//execute_file(char *)
template <typename clock>
int Clock<clock>::execute_file(const std::string &cmdline)
{
#if defined (WINDOWS) || defined (__WINDOWS__) || defined (_WIN64) || defined (_WIN32) || \
defined (WIN64) || defined (WIN32)
return windows_execute(cmdline.c_str());
#elif defined (__linux) || defined (__unix) || defined (__posix) || \
defined (__linux__) || defined (__unix__) || defined (__posix__)
return posix_execute(cmdline.c_str());
#endif // OS-Check
}//execute_file(string)
template <typename clock>
const std::string Clock<clock>::createCmdline(int argc, char *argv[], const int argc_start)
{
std::string cmdline;
for (int i = argc_start; i < argc; ++i) {
bool hs = hasSpace(argv[i]);
if (hs)
cmdline += "\"";
cmdline += argv[i];
if (hs)
cmdline += "\"";
cmdline += " ";
}//for
return cmdline;
}//createCmdline(argc, argv, argc_start)
// private functions
template <typename clock>
bool Clock<clock>::hasSpace(const char *str)
{
char last;
if(str == NULL)
return false;
while('\0' != *str) {
if(((' ' == *str) || ('\t' == *str)) && ('\\' != last))
return true;
last = *str++;
}//while
return false;
}//hasSpace(str)
#if defined (WINDOWS) || defined (__WINDOWS__) || defined (_WIN64) || defined (_WIN32) || \
defined (WIN64) || defined (WIN32)
template <typename clock>
int Clock<clock>::windows_execute(const char *cmdline)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
CreateProcess(NULL, TEXT((char *)cmdline), NULL,
NULL, FALSE, 0,
NULL, NULL, &si,
&pi);
// Start calculating the time
start();
// Wait until child process exits.
WaitForSingleObject(pi.hProcess, INFINITE);
// Process exits, stop the calculation and add to the total_time
pause();
// Get the return value of the child process
DWORD ret;
GetExitCodeProcess(pi.hProcess, &ret);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return ret;
}//windows_execute(const char *)
#elif defined (__linux) || defined (__unix) || defined (__posix) || \
defined (__linux__) || defined (__unix__) || defined (__posix__)
template <typename clock>
int Clock<clock>::posix_execute(const char *cmdline)
{
// Store the return status of the file
int ret_status;
// the child process pid
pid_t pid;
if((pid = fork()) < 0) {
std::cerr << "Errno: " << errno
<< " ErrMsg: " << strerror(errno) << std::endl;
throw std::runtime_error("fork() Failed!");
} else if(pid == 0) {
// child process
execl("/bin/sh", "sh", "-c", cmdline, (char *)0);
// if gets here, execl error
std::cerr << "Errno: " << errno
<< " ErrMsg: " << strerror(errno) << std::endl;
throw std::runtime_error("execl() Failed!");
} else {
// parent process
// start calculating the time
start();
// wait until the file exits
if(waitpid(pid, &ret_status, 0) < 0) {
if(EINTR != errno) {
std::cerr << "Errno: " << errno
<< " ErrMsg: " << strerror(errno) << std::endl;
throw std::runtime_error("waitpid() Failed!");
} else {
// if the process is interupted
ret_status = -1;
}//if-else
}
// stop the calculation and add to the total_time
pause();
}//if-else
return WEXITSTATUS(ret_status);
}//posix_execute(cont char *)
#endif // OS-Check
文件:Clock/test/test.cpp
#include "../Clock"
#include <iostream>
#include <chrono>
#include <sstream>
using namespace std;
using namespace std::chrono;
int main(int argc, char *argv[])
{
if(argc < 2) {
cout << "No argv" << endl;
return 1;
}//if
const int maxn = 100000;
Clock<system_clock> c;
c.start();
for(int i = 0; i < maxn; ++i);
c.pause();
cout << "i 0:" << maxn << endl;
c.print(cout, c.MIN | c.SEC | c.MILLI | c.MICRO, "Clock shows: ");
cout << endl << "clear:" << endl;
c.clear();
c.print(clog);
cout << endl << "addTime, reduceTime:" << endl;
c.addTime(seconds(100));
c.addTime(milliseconds(99));
c.reduceTime(microseconds(1));
c.print();
cout << endl << "toString:" << endl;
system_clock::time_point start_time = c.makeTimePoint(2012, 9, 13);
cout << c.toString(start_time) << endl;
cout << endl << "execute_file: " << endl;
c.clear();
string cmdline = c.createCmdline(argc, argv);
int ret = c.execute_file(cmdline);
stringstream ss;
ss << endl << "Program returns: " << ret << " Time: ";
string ret_str = ss.str();
c.print(cout, c.COMMON,ret_str);
return 0;
}//main