Skip to content

Commit 8b9d803

Browse files
author
zhengshuxin
committed
Add class_counter for check the count of one class obj.
1 parent 4f9d899 commit 8b9d803

File tree

10 files changed

+391
-1
lines changed

10 files changed

+391
-1
lines changed

lib_acl_cpp/include/acl_cpp/lib_acl.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
#include "stdlib/diff_string.hpp"
4343
#include "stdlib/diff_manager.hpp"
4444
#include "stdlib/token_tree.hpp"
45+
//#include "stdlib/type.hpp"
46+
//#include "stdlib/class_counter.hpp"
4547

4648
#include "serialize/gsoner.hpp"
4749
#include "serialize/gson_helper.ipp"

lib_acl_cpp/include/acl_cpp/stdlib/bitmap.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#pragma once
2+
#include "../acl_cpp_define.hpp"
23
#include "noncopyable.hpp"
34

45
namespace acl {
56

6-
class bitmap : public noncopyable {
7+
class ACL_CPP_API bitmap : public noncopyable {
78
public:
89
/**
910
* 构造函数
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#pragma once
2+
#include "../acl_cpp_define.hpp"
3+
#include <map>
4+
#include <string>
5+
#include "singleton.hpp"
6+
7+
#define ACL_COUNTER_INIT(thread_safe) \
8+
acl::class_counter::get_instance().init(thread_safe)
9+
10+
// 某个字符标记增加一次, flagName 为自己定义的唯一字符对象
11+
#define ACL_COUNTER_INC(flagName) \
12+
acl::class_counter::get_instance().inc(#flagName)
13+
14+
// 某个字符标记减少一次
15+
#define ACL_COUNTER_DEC(flagName) \
16+
acl::class_counter::get_instance().dec(#flagName)
17+
18+
#define ACL_COUNTER_COUNT(flagName) \
19+
acl::class_counter::get_instance().count(#flagName)
20+
21+
#define ACL_COUNTER_PRINT() \
22+
acl::class_counter::get_instance().print()
23+
24+
namespace acl {
25+
26+
class thread_mutex;
27+
28+
class ACL_CPP_API class_counter : public singleton<class_counter> {
29+
public:
30+
class_counter();
31+
~class_counter();
32+
33+
/**
34+
* 可以在进程初始化时调用本方法(非必须)进行初始化,指定内部是否需要加锁,
35+
* 如果不调用本方法,内部自动加线程锁.
36+
*/
37+
void init(bool thread_safe = true);
38+
39+
/**
40+
* @brief 将name对应的计数加1,当没有name时设置为1
41+
*/
42+
void inc(const char *name);
43+
44+
/**
45+
* @brief 将name对应的计数减1,当没有name时将输出错误日志
46+
*/
47+
void dec(const char *name);
48+
49+
/**
50+
* @brief 获取name对象的统计个数
51+
*/
52+
long long count(const char *name);
53+
54+
/**
55+
* @brief 输出计数统计
56+
* @param flag 调用者标记
57+
*/
58+
void print(const char *flag = NULL);
59+
60+
private:
61+
std::map<std::string, long long> names_;
62+
thread_mutex* lock_;
63+
};
64+
65+
} // namespace acl
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#pragma once
2+
#include "../acl_cpp_define.hpp"
3+
#include "acl_cpp/stdlib/class_counter.hpp"
4+
#include <string>
5+
6+
#if defined(__GNUC__) || defined(__clang__)
7+
#include <cxxabi.h>
8+
9+
namespace acl {
10+
11+
template<typename T>
12+
std::string get_type_name(const T& obj) {
13+
int status = 0;
14+
char* realname = abi::__cxa_demangle(typeid(obj).name(), NULL, NULL, &status);
15+
std::string result = (status == 0) ? realname : typeid(obj).name();
16+
free(realname);
17+
return result;
18+
}
19+
20+
#else
21+
22+
template<typename T>
23+
std::string get_type_name(const T& obj) {
24+
int status = 0;
25+
std::string result = typeid(obj).name();
26+
return result;
27+
}
28+
29+
#endif
30+
31+
#define ACL_OBJ_INC() do { \
32+
std::string name = acl::get_type_name(*this); \
33+
acl::class_counter::get_instance().inc(name.c_str()); \
34+
} while (0)
35+
36+
#define ACL_OBJ_DEC() do { \
37+
std::string name = acl::get_type_name(*this); \
38+
acl::class_counter::get_instance().dec(name.c_str()); \
39+
} while (0)
40+
41+
} // namespace
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include ../Makefile.in
2+
PROG = class_counter
3+
#CFLAGS += -std=c++11
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#include "stdafx.h"
2+
#include <cxxabi.h>
3+
#include <sys/time.h>
4+
5+
class myobj {
6+
public:
7+
myobj(bool use_typeid) : use_typeid_(use_typeid) {
8+
if (use_typeid) {
9+
ACL_OBJ_INC();
10+
} else {
11+
ACL_COUNTER_INC(myobj);
12+
}
13+
}
14+
15+
virtual ~myobj() {
16+
if (use_typeid_) {
17+
ACL_OBJ_DEC();
18+
} else {
19+
ACL_COUNTER_DEC(myobj);
20+
}
21+
}
22+
23+
protected:
24+
bool use_typeid_;
25+
};
26+
27+
class myobj1 : public myobj {
28+
public:
29+
myobj1(bool use_typeid) : myobj(use_typeid) {
30+
if (use_typeid) {
31+
ACL_OBJ_INC();
32+
} else {
33+
ACL_COUNTER_INC(myobj1);
34+
}
35+
}
36+
37+
~myobj1() {
38+
if (use_typeid_) {
39+
ACL_OBJ_DEC();
40+
} else {
41+
ACL_COUNTER_DEC(myobj1);
42+
}
43+
}
44+
};
45+
46+
class myobj2 : public myobj {
47+
public:
48+
myobj2(bool use_typeid) : myobj(use_typeid) {
49+
if (use_typeid) {
50+
ACL_OBJ_INC();
51+
} else {
52+
ACL_COUNTER_INC(myobj2);
53+
}
54+
}
55+
56+
~myobj2() {
57+
if (use_typeid_) {
58+
ACL_OBJ_DEC();
59+
} else {
60+
ACL_COUNTER_DEC(myobj2);
61+
}
62+
}
63+
};
64+
65+
static void test(size_t max, bool use_typeid) {
66+
std::vector<myobj*> objs;
67+
68+
struct timeval begin, end;
69+
gettimeofday(&begin, NULL);
70+
71+
for (size_t i = 0; i < max; i++) {
72+
myobj* o = new myobj1(use_typeid);
73+
objs.push_back(o);
74+
}
75+
76+
for (size_t i = 0; i < max; i++) {
77+
myobj* o = new myobj2(use_typeid);
78+
objs.push_back(o);
79+
}
80+
81+
gettimeofday(&end, NULL);
82+
double tc = acl::stamp_sub(end, begin);
83+
84+
printf("After add, time cost=%.2f ms, obj: %lld, obj1: %lld, obj2: %lld\r\n",
85+
tc, ACL_COUNTER_COUNT(myobj), ACL_COUNTER_COUNT(myobj1),
86+
ACL_COUNTER_COUNT(myobj2));
87+
88+
ACL_COUNTER_PRINT();
89+
90+
printf("Enter any key to continue...\r\n");
91+
getchar();
92+
93+
for (std::vector<myobj*>::iterator it = objs.begin();
94+
it != objs.end(); ++it) {
95+
delete *it;
96+
}
97+
98+
printf("After del objs: %lld\r\n", ACL_COUNTER_COUNT(myobj));
99+
ACL_COUNTER_PRINT();
100+
}
101+
102+
int main(int argc, char *argv[]) {
103+
// ³õʼ»¯ acl ¿â
104+
acl::acl_cpp_init();
105+
acl::log::stdout_open(true);
106+
107+
size_t max = 1000000;
108+
if (argc > 1) {
109+
max = atol(argv[1]);
110+
}
111+
112+
if (max == 0 || max > 10000000) {
113+
max = 1000000;
114+
}
115+
116+
printf("use_typeid: yes, use_lock: yes\r\n");
117+
test(max, true);
118+
printf("----------------------------------------------------\r\n\r\n");
119+
120+
printf("use_typeid: no, use_lock: yes\r\n");
121+
test(max, false);
122+
printf("----------------------------------------------------\r\n\r\n");
123+
124+
ACL_COUNTER_INIT(false);
125+
126+
printf("use_typeid: yes, use_lock: yes\r\n");
127+
test(max, true);
128+
printf("----------------------------------------------------\r\n\r\n");
129+
130+
printf("use_typeid: no, use_lock: no\r\n");
131+
test(max, false);
132+
133+
return 0;
134+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// stdafx.cpp : 只包括标准包含文件的源文件
2+
// master_threads.pch 将成为预编译头
3+
// stdafx.obj 将包含预编译类型信息
4+
5+
#include "stdafx.h"
6+
7+
// TODO: 在 STDAFX.H 中
8+
//引用任何所需的附加头文件,而不是在此文件中引用
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// stdafx.h : 标准系统包含文件的包含文件,
2+
// 或是常用但不常更改的项目特定的包含文件
3+
//
4+
5+
#pragma once
6+
7+
8+
//#include <iostream>
9+
//#include <tchar.h>
10+
11+
// TODO: 在此处引用程序要求的附加头文件
12+
13+
#include "lib_acl.h"
14+
#include "acl_cpp/lib_acl.hpp"
15+
#include "acl_cpp/stdlib/type.hpp"
16+
17+
#ifdef WIN32
18+
#define snprintf _snprintf
19+
#endif
20+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
valgrind --tool=memcheck --leak-check=yes -v ./class_counter 100

0 commit comments

Comments
 (0)