作者自己写了一个状态机和一个函数指针做TestDriver。但是只能支持Windows,在Linux上无法运行。而且代码中有多处错误。状态机代码也有错误。
修改了一下使其能在Linux上运行。
代码结构如下,
image.png
CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
if(APPLE)
message(STATUS "This is Apple, do nothing.")
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_PREFIX_PATH /Users/aabjfzhu/software/vcpkg/ports/cppwork/vcpkg_installed/x64-osx/share )
elseif(UNIX)
message(STATUS "This is linux, set CMAKE_PREFIX_PATH.")
set(CMAKE_PREFIX_PATH /vcpkg/ports/cppwork/vcpkg_installed/x64-linux/share)
endif(APPLE)
set(Boost_NO_WARN_NEW_VERSIONS 1)
project(optimize)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_definitions(-g)
find_package(ZLIB)
find_package(glog REQUIRED)
find_package(re2 REQUIRED)
find_package(OpenCV REQUIRED )
find_package(OpenSSL REQUIRED)
find_package(Arrow CONFIG REQUIRED)
find_package(unofficial-brotli REQUIRED)
find_package(unofficial-utf8proc CONFIG REQUIRED)
find_package(Thrift CONFIG REQUIRED)
find_package(Boost REQUIRED COMPONENTS
system
filesystem
serialization
program_options
thread
)
find_package(DataFrame REQUIRED)
if(APPLE)
MESSAGE(STATUS "This is APPLE, set INCLUDE_DIRS")
set(INCLUDE_DIRS ${Boost_INCLUDE_DIRS} /usr/local/include /usr/local/iODBC/include /opt/snowflake/snowflakeodbc/include/ ${CMAKE_CURRENT_SOURCE_DIR}/../include/ ${CMAKE_CURRENT_SOURCE_DIR}/../../../include)
set(ARROW_INCLUDE_DIR /Users/aabjfzhu/software/vcpkg/ports/cppwork/vcpkg_installed/x64-osx/include)
elseif(UNIX)
MESSAGE(STATUS "This is linux, set INCLUDE_DIRS")
set(INCLUDE_DIRS ${Boost_INCLUDE_DIRS} /usr/local/include ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/../include /vcpkg/ports/cppwork/vcpkg_installed/x64-linux/include)
set(ARROW_INCLUDE_DIR /vcpkg/ports/cppwork/vcpkg_installed/x64-linux/include)
endif(APPLE)
if(APPLE)
MESSAGE(STATUS "This is APPLE, set LINK_DIRS")
set(LINK_DIRS /usr/local/lib /usr/local/iODBC/lib /opt/snowflake/snowflakeodbc/lib/universal /Users/aabjfzhu/software/vcpkg/ports/cppwork/vcpkg_installed/x64-osx/lib)
elseif(UNIX)
MESSAGE(STATUS "This is linux, set LINK_DIRS")
set(LINK_DIRS ${Boost_INCLUDE_DIRS} /usr/local/lib /vcpkg/ports/cppwork/vcpkg_installed/x64-linux/lib)
endif(APPLE)
if(APPLE)
MESSAGE(STATUS "This is APPLE, set ODBC_LIBS")
set(ODBC_LIBS iodbc iodbcinst)
elseif(UNIX)
MESSAGE(STATUS "This is linux, set ODBC_LIBS")
set(ODBC_LIBS odbc odbcinst ltdl)
endif(APPLE)
include_directories(${INCLUDE_DIRS})
LINK_DIRECTORIES(${LINK_DIRS})
file( GLOB test_file_list ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file( GLOB APP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../include/http/impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../include/yaml/impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../include/df/impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../include/death_handler/impl/*.cpp)
add_library(${PROJECT_NAME}_lib SHARED ${APP_SOURCES} ${test_file})
target_link_libraries(${PROJECT_NAME}_lib ${Boost_LIBRARIES} ZLIB::ZLIB glog::glog DataFrame::DataFrame ${OpenCV_LIBS})
target_link_libraries(${PROJECT_NAME}_lib OpenSSL::SSL OpenSSL::Crypto libgtest.a pystring libyaml-cpp.a libgmock.a ${ODBC_LIBS} libnanodbc.a pthread dl backtrace libzstd.a libbz2.a libsnappy.a re2::re2 parquet lz4 unofficial::brotli::brotlidec-static unofficial::brotli::brotlienc-static unofficial::brotli::brotlicommon-static utf8proc thrift::thrift arrow arrow_dataset)
foreach( test_file ${test_file_list} )
file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${test_file})
string(REPLACE ".cpp" "" file ${filename})
add_executable(${file} ${test_file})
target_link_libraries(${file} ${PROJECT_NAME}_lib)
endforeach( test_file ${test_file_list})
strings_test.cpp
#include "test_driver.h"
#include "stopwatch11.h"
#include <cstdlib>
#include <string>
#include <iostream>
#include <cstring>
// original, naive remove_ctrl()
std::string remove_ctrl(std::string s) {
std::string result;
for (size_t i=0; i<s.length(); ++i) {
if (s[i] >= 0x20)
result = result + s[i];
}
return result;
}
// remove_ctrl() with operator replaced by mutating assignment
std::string remove_ctrl_mutating(std::string s) {
std::string result;
for (size_t i=0; i<s.length(); ++i) {
if (s[i] >= 0x20)
result += s[i];
}
return result;
}
std::string remove_ctrl_mutating_it(std::string s) {
std::string result;
for (auto it=s.begin(); it != s.end(); ++it) {
if (*it >= 0x20)
result += *it;
}
return result;
}
std::string remove_ctrl_mutating_it_end(std::string s) {
std::string result;
for (auto it=s.begin(),end=s.end();it != end; ++it) {
if (*it >= 0x20)
result += *it;
}
return result;
}
// remove_ctrl_mutating() with space reserved in result
std::string remove_ctrl_reserve(std::string s) {
std::string result;
result.reserve(s.length());
for (size_t i=0; i<s.length(); ++i) {
if (s[i] >= 0x20)
result += s[i];
}
return result;
}
std::string remove_ctrl_reserve_it(std::string s) {
std::string result;
result.reserve(s.length());
for (auto it=s.begin(),end=s.end();it != end; ++it) {
if (*it >= 0x20)
result += *it;
}
return result;
}
// remove_ctrl_reserve() with reference arg instead of value arg
std::string remove_ctrl_refs(std::string const& s) {
std::string result;
result.reserve(s.length());
for (size_t i=0; i<s.length(); ++i) {
if (s[i] >= 0x20)
result += s[i];
}
return result;
}
// remove_ctrl_reserve() with reference arg instead of value arg
std::string remove_ctrl_refs_it(std::string const& s) {
std::string result;
result.reserve(s.length());
for (auto it=s.begin(),end=s.end();it != end; ++it) {
if (*it >= 0x20)
result += *it;
}
return result;
}
// remove_ctrl_refs() with reference return value
void remove_ctrl_ref_result(
std::string& result,
std::string const& s) {
result.clear();
result.reserve(s.length());
for (size_t i=0; i<s.length(); ++i) {
if (s[i] >= 0x20)
result += s[i];
}
}
// remove_ctrl_ref_ret with iterators
void remove_ctrl_ref_result_it(
std::string& result,
std::string const& s) {
result.clear();
result.reserve(s.length());
for (auto it=s.begin(),end=s.end();it != end; ++it) {
if (*it >= 0x20)
result += *it;
}
}
// remove_ctrl_ref_result() done with buffers instead of strings
void remove_ctrl_cstrings(char* destp, char const* sourcep, size_t length) {
for (size_t i=0; i<length; ++i) {
if (sourcep[i] >= 0x20)
*destp++ = sourcep[i];
}
*destp = 0;
}
// copy whole substrings to reduce allocations
std::string remove_ctrl_block(std::string s) {
std::string result;
for (size_t b=0,i=b,e=s.length(); b < e; b = i+1) {
for (i=b; i<e; ++i) {
if (s[i] < 0x20) break;
}
result = result + s.substr(b,i-b);
}
return result;
}
// remove_ctrl_block() with mutating concatenation, reserved size
std::string remove_ctrl_block_mutate(std::string s) {
std::string result;
result.reserve(s.length());
for (size_t b=0,i=b,e=s.length(); b < e; b = i+1) {
for (i=b; i<e; ++i) {
if (s[i] < 0x20) break;
}
result += s.substr(b,i-b);
}
return result;
}
std::string remove_ctrl_block_append(std::string s) {
std::string result;
result.reserve(s.length());
for (size_t b=0,i=b; b < s.length(); b = i+1) {
for (i=b; i<s.length(); ++i) {
if (s[i] < 0x20) break;
}
result.append(s, b, i-b);
}
return result;
}
std::string remove_ctrl_block_append_it(std::string s) {
std::string result;
result.reserve(s.length());
for (auto b=s.begin(),i=b; b != s.end(); b = i+1) {
for (i=b; i != s.end(); ++i) {
if (*i < 0x20) break;
}
result.append(b, i);
}
return result;
}
std::string remove_ctrl_block_append_cache(std::string s) {
std::string result;
result.reserve(s.length());
for (size_t b=0,i=b,e=s.length(); b < e; b = i+1) {
for (i=b; i<e; ++i) {
if (s[i] < 0x20) break;
}
result.append(s, b, i-b);
}
return result;
}
std::string remove_ctrl_block_append_cache_it(std::string s) {
std::string result;
result.reserve(s.length());
for (auto b=s.begin(),i=s.begin(),e=s.end(); b != e; b = i+1) {
for (i=b; i != e; ++i) {
if (*i < 0x20) break;
}
result.append(b, i);
}
return result;
}
// remove_ctrl_block_mutate() with reference arg
std::string remove_ctrl_blocks(std::string const& s) {
std::string result;
result.reserve(s.length());
for (size_t b=0,i=b,e=s.length(); b < e; b = i+1) {
for (i=b; i<e; ++i) {
if (s[i] < 0x20) break;
}
result.append(s, b,i-b);
}
return result;
}
// remove_ctrl_blocks() with reference return value
void remove_ctrl_block_ret(std::string& result, std::string const& s) {
result.clear();
result.reserve(s.length());
for (size_t b=0,i=b,e=s.length(); b < e; b = i+1) {
for (i=b; i<e; ++i) {
if (s[i] < 0x20) break;
}
result.append(s, b, i-b);
}
}
void remove_ctrl_block_ret_it(std::string& result, std::string const& s) {
result.clear();
result.reserve(s.length());
for (auto b=s.begin(),i=b,e=s.end(); b != e; b = i+1) {
for (i=b; i != e; ++i) {
if (*i < 0x20) break;
}
result.append(b, i);
}
}
// cleverly reduce the size of a string so it doesn't have to be reallocated
std::string remove_ctrl_erase(std::string s) {
for (size_t i = 0; i < s.length(); )
if (s[i] < 0x20)
s.erase(i,1);
else ++i;
return s;
}
std::string remove_ctrl_erase_it(std::string s) {
for (auto i = s.begin(); i != s.end(); )
if (*i < 0x20)
s.erase(i);
else ++i;
return s;
}
int test_strings(int test_no, unsigned long multiplier) {
typedef unsigned counter_t;
counter_t iterations = 1000*multiplier;
std::string s("\07Now is the time\07 for all good men\r\n to come to the aid of their country. \07");
std::string test("Now is the time for all good men to come to the aid of their country. ");
std::string result;
s = s + s + s;
test = test + test + test;
bool rc = true;
switch (test_no) {
default: return -1;
case 0: return 12;
case 1:
# if defined _WIN32
# if defined _DEBUG
std::cout << "Windows debug build" << std::endl;
# else
std::cout << "Windows release build" << std::endl;
# endif
# else
std::cout << "Linux build" << std::endl;
# endif
std::cout << s.length() << " character argument to remove_ctrl()" << std::endl;
std::cout << iterations << " iterations" << std::endl;
result = remove_ctrl(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_mutating(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_mutating_it(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_reserve(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_reserve_it(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_refs(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_refs_it(s);
rc &= (result.compare(test) == 0);
remove_ctrl_ref_result(result, s);
rc &= (result.compare(test) == 0);
remove_ctrl_ref_result_it(result, s);
rc &= (result.compare(test) == 0);
{
char a[1000];
memset(a, 0, sizeof(a));
remove_ctrl_cstrings(a, s.data(), s.length());
rc &= (strcmp(a, test.data()) == 0);
// memset(a, 0, sizeof(a));
// remove_ctrl_6(a, s.data(), s.length());
// rc &= (strcmp(a, test.data()) == 0);
}
result = remove_ctrl_block(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_block_mutate(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_block_append(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_block_append_it(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_block_append_cache(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_block_append_cache_it(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_blocks(s);
rc &= (result.compare(test) == 0);
remove_ctrl_block_ret(result, s);
rc &= (result.compare(test) == 0);
remove_ctrl_block_ret(result, s);
rc &= (result.compare(test) == 0);
remove_ctrl_block_ret_it(result, s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_erase(s);
rc &= (result.compare(test) == 0);
result = remove_ctrl_erase_it(s);
rc &= (result.compare(test) == 0);
break;
case 2:
{
Stopwatch sw("remove_ctrl()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl(s);
}
rc &= (result.compare(test) == 0);
break;
case 3:
{ Stopwatch sw("remove_ctrl_mutating()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_mutating(s);
}
rc &= (result.compare(test) == 0);
{ Stopwatch sw("remove_ctrl_mutating_it()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_mutating_it(s);
}
rc &= (result.compare(test) == 0);
{ Stopwatch sw("remove_ctrl_mutating_it_end()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_mutating_it_end(s);
}
rc &= (result.compare(test) == 0);
break;
case 4:
{ Stopwatch sw("remove_ctrl_reserve()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_reserve(s);
}
rc &= (result.compare(test) == 0);
{ Stopwatch sw("remove_ctrl_reserve_it()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_reserve_it(s);
}
rc &= (result.compare(test) == 0);
break;
case 5:
{ Stopwatch sw("remove_ctrl_refs()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_refs(s);
}
rc &= (result.compare(test) == 0);
{ Stopwatch sw("remove_ctrl_refs_it()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_refs_it(s);
}
rc &= (result.compare(test) == 0);
break;
case 6:
{ Stopwatch sw("remove_ctrl_ref_result()");
for (counter_t i = 0; i < iterations; ++i)
remove_ctrl_ref_result(result, s);
}
rc &= (result.compare(test) == 0);
{ Stopwatch sw("remove_ctrl_ref_it()");
for (counter_t i = 0; i < iterations; ++i)
remove_ctrl_ref_result_it(result, s);
}
rc &= (result.compare(test) == 0);
break;
case 7: {
Stopwatch sw("remove_ctrl_cstrings()");
for (counter_t i = 0; i < iterations; ++i) {
char a[1000];
remove_ctrl_cstrings(a, s.data(), s.length());
}
}
rc &= (result.compare(test) == 0);
break;
case 8: {
Stopwatch sw("remove_ctrl_block()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_block(s);
}
rc &= (result.compare(test) == 0);
break;
case 9:
{ Stopwatch sw("remove_ctrl_block_mutate()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_block_mutate(s);
}
rc &= (result.compare(test) == 0);
{ Stopwatch sw("remove_ctrl_block_append()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_block_append(s);
}
rc &= (result.compare(test) == 0);
{ Stopwatch sw("remove_ctrl_block_append_it()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_block_append_it(s);
}
rc &= (result.compare(test) == 0);
{ Stopwatch sw("remove_ctrl_block_append_cache()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_block_append_cache(s);
}
rc &= (result.compare(test) == 0);
{ Stopwatch sw("remove_ctrl_block_append_cache_it()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_block_append_cache_it(s);
}
rc &= (result.compare(test) == 0);
break;
case 10: {
Stopwatch sw("remove_ctrl_blocks()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_blocks(s);
}
rc &= (result.compare(test) == 0);
break;
case 11:
{ Stopwatch sw("remove_ctrl_block_ret()");
for (counter_t i = 0; i < iterations; ++i)
remove_ctrl_block_ret(result, s);
}
rc &= (result.compare(test) == 0);
{ Stopwatch sw("remove_ctrl_block_ret_it()");
for (counter_t i = 0; i < iterations; ++i)
remove_ctrl_block_ret_it(result, s);
}
rc &= (result.compare(test) == 0);
break;
case 12:
{ Stopwatch sw("remove_ctrl_erase()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_erase(s);
}
rc &= (result.compare(test) == 0);
{ Stopwatch sw("remove_ctrl_erase_it()");
for (counter_t i = 0; i < iterations; ++i)
result = remove_ctrl_erase_it(s);
}
rc &= (result.compare(test) == 0);
break;
}
return rc ? 1 : 0;
}
int main(int argc, char* argv[]) {
test_driver(test_strings, argc, argv);
return EXIT_SUCCESS;
}
include/test_driver.h
#ifndef _FREDRIC_TEST_DRIVER_H_
#define _FREDRIC_TEST_DRIVER_H_
typedef int (*testfunc)(int, unsigned long);
void test_driver(testfunc* flist, int argc=0, char** argv=0);
void test_driver(testfunc f, int argc=0, char** argv=0);
#endif
include/stop_watch.h
#ifndef STOPWATCH_H
#define STOPWATCH_H
#include <iostream>
/* class Stopwatch -- simple stopwatch timer for optimization
Stopwatch prints out elapsed time information for measuring the run time
of long-running tasks. Stopwatch can also return the elapsed time without
printing anything.
Stopwatch is meant to be used with the RAII idiom. In its
simplest use, the block
{
Stopwatch sw("TheThing()");
TheThing();
}
produces two lines of output like
TheThing(): start
// anything printed by TheThing()
TheThing(): stop 63mS
Stopwatch is meant to replace something more complex like
{
timeval t1, t2;
long dt;
gettimeofday(&t1, NULL);
TheThing();
gettimeofday(&t2, NULL);
dt = (t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec);
std::cout << "TheThing() took " << dt/1000 << " mS" << std::endl;
}
What it prints
ctor(): "Stopwatch: start"
ctor(false): nothing printed
Show(): "Stopwatch: show at xxxx mS"
sets lap time. Get with LapGet()
Stop(): "Stopwatch: stop xxxx mS"
sets lap time. Get with LapGet()
Stop() when not running: "Stopwatch: not started"
Start(): "Stopwatch: start"
clears lap time
Start() when running: "Stopwatch: start xxxx mS"
sets lap time. Get with LapGet()
What it prints when activity name is specified
ctor("activity"): "activity: start"
Show("theEvent"): "activity: theEvent at xxxx mS"
Stop("theEvent"): "activity: theEvent xxxx mS"
sets lap time. Get with LapGet()
Stop("theEvent") not running: "activity: not started"
Start("theEvent") running: "activity: theEvent xxxx mS"
sets lap time. Get with LapGet()
Start("theEvent") not running: "activity: theEvent"
clears lap time
printing can be suppressed (get time using LapGet()
ctor("") or ctor(nullptr) prints nothing
Show("") or Show(nullptr) prints nothing, sets lap time
Start("") or Start(nullptr): prints nothing, sets lap time if running
Stop("") or Stop(nullptr): sets lap time. Get with LapGet()
*/
template <typename T> class basic_stopwatch : public T {
public:
typedef T BaseTimer;
typedef typename T::tick_t tick_t;
// create, optionally start timing an activity
explicit basic_stopwatch(bool start);
explicit basic_stopwatch(char const* activity = "Stopwatch",
bool start=true);
basic_stopwatch(std::ostream& log,
char const* activity="Stopwatch",
bool start=true);
// stop and destroy a stopwatch
~basic_stopwatch();
// get last lap time (time of last stop)
tick_t LapGet() const;
// predicate: return true if the stopwatch is running
bool IsStarted() const;
// show accumulated time, keep running, set/return lap
tick_t Show(char const* event="show");
// (re)start a stopwatch, set/return lap time
tick_t Start(char const* event_namee="start");
// stop a running stopwatch, set/return lap time
tick_t Stop(char const* event_name="stop");
private: // members
char const* m_activity; // "activity" string
tick_t m_lap; // lap time (time of last stop or 0)
std::ostream& m_log; // stream on which to log events
};
// performs a Start() if start_now == true
template <typename T> inline basic_stopwatch<T>::basic_stopwatch(bool start_now)
: m_activity("Stopwatch")
, m_lap(0)
, m_log(std::cout)
{
if (start_now)
Start();
}
// performs a start if start_now == true, suppress print by ctor("")
template <typename T> inline basic_stopwatch<T>::basic_stopwatch(char const* activity, bool start_now)
: m_activity(activity && activity[0] ? activity : nullptr)
, m_lap(0)
, m_log(std::cout)
{
if (start_now) {
if (m_activity)
Start();
else
Start(nullptr);
}
}
// set log output, optional printout, optional start
template <typename T> inline basic_stopwatch<T>::basic_stopwatch(std::ostream& log, char const* activity, bool start_now)
: m_activity(activity && activity[0] ? activity : nullptr)
, m_lap(0)
, m_log(log)
{
if (start_now) {
if (m_activity)
Start();
else
Start(nullptr);
}
}
// stop/destroy stopwatch, print message if activity was set in ctor
template <typename T> inline basic_stopwatch<T>::~basic_stopwatch() {
if (IsStarted()) {
if (m_activity)
Stop();
else
Stop(nullptr);
}
}
// predicate: return true if the stopwatch is running
template <typename T> inline bool basic_stopwatch<T>::IsStarted() const
{
return BaseTimer::IsStarted();
}
// get the last lap time (time of last stop)
template <typename T> inline typename basic_stopwatch<T>::tick_t basic_stopwatch<T>::LapGet() const
{
return m_lap;
}
// show accumulated time, keep running, get/return lap time
template <typename T> inline typename basic_stopwatch<T>::tick_t basic_stopwatch<T>::Show(char const* event_name) {
if (IsStarted()) {
m_lap = BaseTimer::GetMs();
if (event_name && event_name[0]) {
if (m_activity)
m_log << m_activity << ": ";
m_log << event_name << " at " << m_lap << "mS" << std::endl << std::flush;
}
}
else {
if (m_activity)
m_log << m_activity << ": not started" << std::endl << std::flush;
}
return m_lap;
}
// (re)start a stopwatch, set/return lap time
template <typename T> inline typename basic_stopwatch<T>::tick_t basic_stopwatch<T>::Start(char const* event_name) {
if (IsStarted()) {
Stop(event_name);
}
else {
if (event_name && event_name[0]) {
if (m_activity)
m_log << m_activity << ": ";
m_log << event_name << std::endl << std::flush;
}
}
BaseTimer::Start();
return m_lap;
}
// stop a running stopwatch and print the accumulated time
template <typename T> inline typename basic_stopwatch<T>::tick_t basic_stopwatch<T>::Stop(char const* event_name) {
if (IsStarted()) {
m_lap = BaseTimer::GetMs();
if (event_name && event_name[0]) {
if (m_activity)
m_log << m_activity << ": ";
m_log << event_name << " " << m_lap << "mS" << std::endl << std::flush;
}
}
BaseTimer::Clear();
return m_lap;
}
# endif
include/stopwatch11.h
#ifndef STOPWATCH11_H
#define STOPWATCH11_H
#include <chrono>
using namespace std::chrono;
class TimerBaseChrono {
public:
typedef unsigned long tick_t;
// clears the timer
TimerBaseChrono() : m_start(system_clock::time_point::min()) { }
// clears the timer
void Clear() {
m_start = system_clock::time_point::min();
}
// returns true if the timer is running
bool IsStarted() const {
return (m_start != system_clock::time_point::min());
}
// start the timer
void Start() { m_start = std::chrono::system_clock::now(); }
// get the number of milliseconds since the timer was started
unsigned long GetMs() {
if (IsStarted()) {
system_clock::duration diff;
diff = system_clock::now() - m_start;
return (unsigned)(duration_cast<milliseconds>(diff).count());
}
return 0;
}
private:
std::chrono::system_clock::time_point m_start;
};
#include "stopwatch.h"
typedef basic_stopwatch<TimerBaseChrono> Stopwatch;
# endif
include/priority_thread.h
#ifndef _PRIORITY_THREAD_H_
#define _PRIORITY_THREAD_H_
#include <unistd.h>
#include <pthread.h>
struct PriorityThread {
int policy;
int old_priority;
sched_param param;
PriorityThread();
~PriorityThread();
};
#endif
impl/priority_thread.cpp
#include "priority_thread.h"
#include <iostream>
PriorityThread::PriorityThread() {
// 设置当前进程nice值为最低,设为最高优先级进程
nice(-20);
// 获取当前优先级
pthread_getschedparam(pthread_self(), &policy, ¶m);
old_priority = param.sched_priority;
// 设置当前线程优先级为最高优先级
param.sched_priority = sched_get_priority_max(policy);
pthread_setschedparam(pthread_self(), policy, ¶m);
}
PriorityThread::~PriorityThread() {
// 设置当前进程nice值为最高,降低优先级
nice(19);
// 设置优先级为普通线程优先级
param.sched_priority = old_priority;
pthread_setschedparam(pthread_self(), policy, ¶m);
}
impl/stopwatch11.cpp
# include "stopwatch11.h"
# include <thread>
void Sleep(unsigned ms)
{
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
int test_stopwatch11(int test_no, unsigned long)
{
bool rc = true;
switch (test_no)
{
default: return -1;
case 0: return 4;
case 1: {
TimerBaseChrono tb;
tb.Start();
Sleep(5);
unsigned dt1 = tb.GetMs();
Sleep(20);
unsigned dt2 = tb.GetMs();
Sleep(35);
unsigned dt3 = tb.GetMs();
break;
}
case 2: {
Stopwatch sw;
Sleep(15);
unsigned dt1 = sw.Show();
rc &= (dt1 == sw.LapGet());
rc &= (15 <= dt1 && dt1 <= 32);
Sleep(25);
unsigned dt2 = sw.Show();
rc &= (dt2 == sw.LapGet());
rc &= (dt1 + 25 <= dt2 && dt2 <= dt1 + 32);
Sleep(15);
unsigned dt3 = sw.Stop();
rc &= (dt3 == sw.LapGet());
rc &= (dt2 + 15 <= dt3 && dt3 <= dt2 + 32);
break;
}
case 3: {
Stopwatch sw("timing run", false);
Sleep(10);
unsigned dt1 = sw.Start();
rc &= (dt1 == 0);
Sleep(15);
unsigned dt2 = sw.Start("event1");
rc &= (15 <= dt2 && dt2 <= 32);
Sleep(25);
unsigned dt3 = sw.Start("event2");
rc &= (25 <= dt3 && dt3 <= 32);
Sleep(5);
unsigned dt4 = sw.Stop("event3");
rc &= (5 <= dt4 && dt4 <= 16);
break;
}
case 4: {
Stopwatch sw("");
Sleep(15);
unsigned dt1 = sw.Show("");
rc &= (15 <= dt1 && dt1 <= 32);
unsigned dt2 = sw.Start("");
rc &= (15 <= dt2 && dt2 <= 32);
break;
}
}// end switch
return rc ? 1 : 0;
}
impl/test_driver.cpp
#include "test_driver.h"
#include "priority_thread.h"
#include <iostream>
#include <cstring>
// os-independent except for PriorityThread
void test_driver(testfunc* flist, int argc, char** argv)
{
unsigned long multiplier = 1;
if (argc > 1) {
if (strncmp(argv[1], "-x", 2) == 0)
multiplier = strtoul(argv[1]+2, nullptr, 10);
}
if (flist == nullptr) {
std::cout << "No test function" << std::endl;
}
else {
std::cout << "multiplier set to " << multiplier << std::endl;
PriorityThread p;
for (unsigned f = 0; flist[f] != 0; ++f) {
if (flist[f] == nullptr)
continue;
if (flist[f](1, multiplier) == 1)
std::cout << "All tests pass" << std::endl;
else
std::cout << "tests failed" << std::endl;
for (int i = 2, e = flist[f](0, multiplier); i <= e; ++i)
if (flist[f](i, multiplier) != 1)
std::cout << "test " << i << " failed" << std::endl;
}
}
}
void test_driver(testfunc f, int argc, char** argv)
{
unsigned long multiplier = 1;
if (argc > 1) {
if (strncmp(argv[1], "-x", 2) == 0)
multiplier = strtoul(argv[1]+2, nullptr, 10);
}
if (f == nullptr) {
std::cout << "No test function" << std::endl;
}
else {
std::cout << "multiplier set to " << multiplier << std::endl;
PriorityThread p;
if (f(1, multiplier) == 1)
std::cout << "All tests pass" << std::endl;
else
std::cout << "tests failed" << std::endl;
for (int i = 2, e = f(0, multiplier); i <= e; ++i)
if (f(i, multiplier) != 1)
std::cout << "test " << i << " failed" << std::endl;
}
}
程序输出如下,
image.png
网友评论