本计时器精确到微秒。目前版本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