我正在编写一个通用的抽象类,以便能够根据需要报告任意数量的实例变量的状态.例如,考虑以下无用循环:
int a, b; for (int i=0; i < 10000; ++i) { for (int j=0; j < 1000; ++j) { for (int k =0; k < 1000; ++k) { a = i; b = j; } } }
能够看到a
和b
不必修改循环的值是很好的.在过去,我写过if语句,如下所示:
int a, b; for (int i=0; i < 10000; ++i) { for (int j=0; j < 1000; ++j) { for (int k =0; k < 1000; ++k) { a = i; b = j; if (a % 100 == 0) { printf("a = %d\n", a); } } } }
这将允许我看到a
每100次迭代的值.但是,根据正在进行的计算,有时无法以这种方式检查进度.我们的想法是能够离开计算机,在给定时间后回来并检查您想要看到的任何值.
为此我们可以使用pthreads
.以下代码有效,我发布它的唯一原因是因为我不确定我是否正确使用该线程,主要是如何关闭它.
首先让我们考虑文件"reporter.h":
#include#include #include void* run_reporter(void*); class reporter { public: pthread_t thread; bool stdstream; FILE* fp; struct timespec sleepTime; struct timespec remainingSleepTime; const char* filename; const int sleepT; double totalTime; reporter(int st, FILE* fp_): fp(fp_), filename(NULL), stdstream(true), sleepT(st) { begin_report(); } reporter(int st, const char* fn): fp(NULL), filename(fn), stdstream(false), sleepT(st) { begin_report(); } void begin_report() { totalTime = 0; if (!stdstream) fp = fopen(filename, "w"); fprintf(fp, "reporting every %d seconds ...\n", sleepT); if (!stdstream) fclose(fp); pthread_create(&thread, NULL, run_reporter, this); } void sleep() { sleepTime.tv_sec=sleepT; sleepTime.tv_nsec=0; nanosleep(&sleepTime, &remainingSleepTime); totalTime += sleepT; } virtual void report() = 0; void end_report() { pthread_cancel(thread); // Wrong addition of remaining time, needs to be fixed // but non-important at the moment. //totalTime += sleepT - remainingSleepTime.tv_sec; long sec = remainingSleepTime.tv_sec; if (!stdstream) fp = fopen(filename, "a"); fprintf(fp, "reported for %g seconds.\n", totalTime); if (!stdstream) fclose(fp); } }; void* run_reporter(void* rep_){ reporter* rep = (reporter*)rep_; while(1) { if (!rep->stdstream) rep->fp = fopen(rep->filename, "a"); rep->report(); if (!rep->stdstream) fclose(rep->fp); rep->sleep(); } }
该文件声明了抽象类reporter
,注意纯虚函数report
.这是将打印消息的功能.每个记者都有自己的,thread
并在reporter
调用构造函数时创建线程.要reporter
在我们无用的循环中使用该对象,我们现在可以:
#include "reporter.h" int main() { // Declaration of objects we want to track int a = 0; int b = 0; // Declaration of reporter class prog_reporter: public reporter { public: int& a; int& b; prog_reporter(int& a_, int& b_): a(a_), b(b_), reporter(3, stdout) {} void report() { fprintf(fp, "(a, b) = (%d, %d)\n", this->a, this->b); } }; // Start tracking a and b every 3 seconds prog_reporter rep(a, b); // Do some useless computation for (int i=0; i < 10000; ++i) { for (int j=0; j < 1000; ++j) { for (int k =0; k < 1000; ++k) { a = i; b = j; } } } // Stop reporting rep.end_report(); }
在编译此代码(没有优化标志)并运行它后,我获得:
macbook-pro:Desktop jmlopez$ g++ testing.cpp macbook-pro:Desktop jmlopez$ ./a.out reporting every 3 seconds ... (a, b) = (0, 60) (a, b) = (1497, 713) (a, b) = (2996, 309) (a, b) = (4497, 478) (a, b) = (5996, 703) (a, b) = (7420, 978) (a, b) = (8915, 78) reported for 18 seconds.
这正是我想要它做的事情,然后我得到优化标志:
macbook-pro:Desktop jmlopez$ g++ testing.cpp -O3 macbook-pro:Desktop jmlopez$ ./a.out reporting every 3 seconds ... (a, b) = (0, 0) reported for 0 seconds.
这并不奇怪,因为编译器可能会重写我的代码,以便在更短的时间内给出相同的答案.我原来的问题是,如果我让循环更长,记者没有给我变量的值,例如:
for (int i=0; i < 1000000; ++i) { for (int j=0; j < 100000; ++j) { for (int k =0; k < 100000; ++k) { a = i; b = j; } } }
使用优化标志再次运行代码后:
macbook-pro:Desktop jmlopez$ g++ testing.cpp -O3 macbook-pro:Desktop jmlopez$ ./a.out reporting every 3 seconds ... (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) (a, b) = (0, 0) reported for 39 seconds.
问题:这个输出是由于优化标志修改了代码,它只是决定不更新变量直到最后?
在reporter
方法中end_report
我调用函数pthread_cancel
.在阅读了以下答案后,它让我怀疑该功能的使用以及我如何终止报告线程.对于那些经验丰富的人来说pthreads
,有没有明显的漏洞或使用thread
我所做的潜在问题?