重构常规c++代码模式
Refactor regular C++ code pattern
总结:我想看看我是否可以重构一些有规则模式的c++代码,使其更容易更新和维护。
:
我有一些代码创建线程本地计数器来跟踪程序执行期间的统计信息。目前,当一个统计数据被添加到源代码时,有5个东西需要更新:计数器线程局部声明,计数器总数声明,重置线程计数器的函数,将线程计数器添加到总数的函数,以及打印函数。
代码如下:
// Adding a statistic named 'counter'
// Declaration of counter
__thread int counter = 0;
int total_counter = 0;
// In reset function
counter = 0;
// In add function
total_counter += counter;
// In print function
printf("counter value is: %dn", total_counter);
我可以看到如何为计数器的声明创建宏,这样做:
#define STAT(name) __thread int name;
int total_##name;
但是我还没有想到如何扩展它来更新add
和reset
函数。理想情况下,我想输入像STAT(counter)
这样的东西,并有管理统计数据的所有声明和函数。
编辑:
我已经有了用于更新代码中的统计信息的宏。像STAT_INC(counter)
这样的东西会增加本地计数器的值。然后,当线程完成执行时,它的线程本地值被添加到总体总数中。所以每个统计数据的名称很重要,这就是为什么数组不适合我。因为真正的计数器名称是像cache_hit
这样的东西,它比counter[2]
更有意义,而且我不想失去为创建的统计数据使用任意名称的能力。如果可能的话,只是为了简化在声明统计数据时必须编写的代码量。
这将使您在问题中描述的内容或多或少地封装在模板类中:
enum StatNames {
STAT_rx_bytes,
STAT_tx_bytes,
//...,
};
template <StatNames SN>
class Stat {
static const char *name_;
static __thread int x_;
static int total_;
public:
Stat(const char *name) { name_ = name; }
static void reset () { x_ = 0; }
static void add () { total_ += x_; }
static void print () {
std::cout << name_ << " value is: " << total_ << "n";
}
static int & x () { return x_; }
static int total () { return total_; }
};
template <StatNames SN> const char * Stat<SN>::name_;
template <StatNames SN> __thread int Stat<SN>::x_;
template <StatNames SN> int Stat<SN>::total_;
#define STAT(name) Stat<STAT_##name> name(#name)
然后可以编写如下代码:
STAT(rx_bytes);
void * test (void *)
{
rx_bytes.x() += 4;
rx_bytes.add();
std::cout << pthread_self() << ": " << rx_bytes.x() << "n";
return 0;
}
int main ()
{
pthread_t t[2];
pthread_create(&t[0], 0, test, 0);
pthread_create(&t[1], 0, test, 0);
pthread_join(t[0], 0);
pthread_join(t[1], 0);
rx_bytes.print();
}
(7分钟后无人接听…我收到礼物了!)
所以基本上你不需要五个独立的命名变量。可以使用数组或向量:
int counters[5];
那么更新某个计数器就很容易了:
class Counter {
int counters[5];
void update_nth(int n)
{
counters[n]++;
}
};
与所有其他变量类似。
接着H2CO3的回答,有一个常见的成语,看起来像这样:
enum CounterEnums {
MyFirstCounter,
MySecondCounter,
// ... add new counter names here ...
NumCounters
};
class Counter {
int counters[NumCounters];
public:
void update(int n) { counters[n]++; }
};
现在,您可以轻松地添加另一个计数器,只需将其放在 NumCounters
之前。现在,您可以声明您的实例,类似于:
Counter totals; // global
boost::thread_specific_pointer<Counter> counters; // per-thread
使用和
counters->update(MyFirstCounter);
(你还需要一些方法来更新totals
和零你的每线程计数器,但我会…
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- С++ wxWidgets:代码架构,设计原则和模式
- Visual Studio 发布模式阻止在调试模式下执行的代码.使用 WinHTTP 和多线程
- 使用Qt Creator在调试模式下编译一段代码
- 使用哪种模式来执行新代码,只需添加基类的新子类?
- 在 directx11 代码中更改全屏模式下的刷新率不起作用
- C++单例模式代码无法运行,不知道为什么?
- 我的代码在发布模式下不起作用,而在Qt的调试模式下工作
- 我如何调用在调试模式下具有主要的程序或代码
- 该代码在调试模式下工作,但在发布模式C 中不起作用
- OPENCV解码灰色代码模式相机校准错误.如何格式化固有和外在结果
- 原型模式导致"actual object"和"prototype"之间的代码重复
- 此代码是否代表设计模式
- 在非调试模式下运行代码时出现问题
- C++ 装饰设计模式 - 代码有效但不知道为什么
- 抽象工厂模式客户端代码
- C/C++中的6502仿真器:如何将寻址模式代码与实际指令代码分离
- 代码设计:观察者模式
- 如何将基本代码截图/模式转换为使用 c+11 可变参数模板
- 64 位模式下 .asm 文件中的内联代码