# 基础类库说明

该文档描述了基础工具类。这些工具类能够快速方便的帮你完成开发, 强烈推荐你使用!

**关于线程安全：**

* 所有类的静态函数都是线程安全的；
* 除了TC\_Thread开头的类是线程安全外，其他类都不是线程安全的(不能两个线程同时操作一个对象)；
* 如果只是只读，则是线程安全的；

## 异常类

### TC\_Exception

异常基类，所有的异常都直接或者间接继承与它；

构造函数中，提供了一个可以传入errno的构造函数，异常抛出时直接获取strerror(errno)的错误信息；

建议用:TC\_Exception::getSystemCode() 获取错误码, windows下是GetLastError(), linux/mac下是errno, 用TC\_Exception::parseError(TC\_Exception::getSystemCode())获取错误信息.

## 帮助类

### TC\_Common

**基础工具类，提供了一些非常基本的函数使用。**

这些函数都是以静态函数提供。

包括以下几种函数：

* Trim类函数：trim,trimLeft,trimRight；
* 大小写转换函数：lower、upper；
* 分隔字符串函数：sepstr （直接分隔字符串，数字等）
* 时间相关函数：str2tm、tm2str、now2str、tm2GMTstr、now2GMTstr、now2us；
* 字符串转换函数：tostr、strto；
* 二进制字符串互转函数：bin2str、str2bin；
* 替换字符串函数：replace；
* Ip匹配函数：matchPeriod；
* 其他常用的函数

### TC\_File

**文件相关的操作。**

这些函数都是以静态函数提供。

* 获取文件大小：getFileSize
* 是否是绝对路径：isAbsolute
* 文件是否存在：isFileExist，isFileExistEx
* 规则化目录：simplifyDirectory
* 创建目录：makeDir、makeDirRecuresive
* 设置文件可执行：setExecutable(windows下没有)、canExecutable
* 删除文件：removeFile
* 读取小文件到内存(string)：load2str
* 写内存(string)到文件：save2file
* 获取文件可执行路径：getExePath
* 分析文件名称：extraceFileName、extractFilePath、extractFileExt、excludeFileExt、replaceFileExt、extractUrlFilePath
* 遍历目录：scanDir、listDirectory
* 拷贝文件：copyFile

## 编解码、加密类

### TC\_Des

* des的加密/解密函数；
* 3des加密/解密函数；
* 函数以静态形式提供，线程安全；
* des/3des加密解密源码, 不依赖任何库
* 网上流行的d3des.h d3des.c修改完成；
* Key必须是null结束的字符串.

**对于des加密：**

* 8位密钥,不足8位的右补0x00;
* 多余8位,只取左8位有效;
* 加密内容8位补齐,补齐方式为:少1位补一个0x01,少2位补两个0x02,...
* 本身已8位对齐的,后面补八个0x08

**对于3des加解密:**

* 只支持3des-ecb加密方式；
* 24位密钥,不足24位的右补0x00;
* 多余24位,只取左24位有效;
* 加密内容8位补齐，补齐方式为：少1位补一个0x01,少2位补两个0x02,...
* 本身已8位对齐的，后面补八个0x08;

```cpp
#define KEY  "dRa93seg"
#define KEY3 " dRa93segdRa93seg dRa93seg"

string n = "abde";
{
    string s = n;
    cout << "des encrypt:" << s << endl;
    string v = taf::TC_Des::encrypt(KEY, s.c_str(), s.length());
    cout << "encrypt:" << TC_Common::bin2str(v) << endl;
    string s1 = TC_Des::decrypt(KEY, v.c_str(), v.length());
    cout << "des decrypt:" << s1 << endl;
}

{
    string s = n;
    cout << "encrypt:" << s << endl;
    string v = taf::TC_Des::encrypt3(KEY3, s.c_str(), s.length());
    cout << "encrypt:" << TC_Common::bin2str(v.c_str()) << endl;
    string s1 =TC_Des::decrypt3(KEY3, v.c_str(), v.length());
    cout << "decrypt:" << s1 << endl;
}
```

### TC\_Base64

标准base64的编解码函数，通过静态函数提供。

```cpp
string src = “abc”;
//编码
string dest =TC_Base64::encode(src);
//解码
string src1 = TC_Base64::decode(dest);
assert(src == src1);
```

### TC\_MD5

Md5的散列算法，通过静态函数提供。

```cpp
string src = “test”;
string hs = TC_MD5::md5str(src);
cout << hs << endl;
```

### TC\_Encoder

Gbk到utf8之间的相互转码函数，通过静态函数提供。

```cpp
string s = "我们";
string v = TC_Encoder::gbk2utf8(s);
cout << s << ":" << v << ":" << TC_Encoder::utf82gbk(v) << endl;
```

该类也提供了**transTo/transFrom**函数用于将string的\n替换掉，或从替换的数据恢复源数据，主要用于将string记录在一行，通常用于写**bin-log**的地方。

### TC\_Pack

* 二进制的组包解包类，通过`<<、>>`操作符实现；
* 对string，采用了压缩格式：长度`<255: 1个字节长度, 内容；长度>`=255, 4个字节(长度), 内容；
* 所有整形/长度值都采用字节序；
* **非线程安全；**

### TC\_Parsepara

* 提供name=value\&name1=value1形式的解析函数；
* 可以和map互相转换；
* 不是标准的cgi参数的解析（标准cgi参数解析会把空格和+互转）；
* **非线程安全；**

## 锁类

注意:对于线程锁,TAF5.0可以直接使用c++11的锁了!这些类的存在是为了兼容TAF低版本!

### TC\_SemMutex

* 进程锁, 可以跨进程加锁
* Linux/Mac下IPC信号量锁，进程、线程间锁；
* Windows使用的Mutex/Event实现
* 提供了读写锁功能；

### TC\_LockT

* 模板锁类，和其他具体锁配合使用。
* 构造时候加锁，析够的时候解锁；
* TC\_TryLockT类似，用于锁尝试操作；
* TC\_EmptyMutex：空锁，不提供任何操作；
* 其他具体锁的加解锁函数一样，保证能够和TC\_LockT配合使用；

```cpp
TC_SemMutex sm;
sm.init(8888);
TC_LockT<TC_SemMutex> sync(sm);

TC_ThreadMutex tm;
TC_LockT< TC_ThreadMutex > sync(tm);
```

### TC\_ThreadMutex

* 线程锁，不可重复加锁，即同一个线程不可以重复加锁;
* 通常不直接使用，和TC\_Monitor配合使用，即TC\_ThreadLock;

### TC\_ThreadRecMutex

* 线程锁，可重复加锁，即同一个线程可以重复加锁;
* 通常不直接使用，和TC\_Monitor配合使用，即TC\_ThreadRecLock;

### TC\_ThreadRWLock

* 线程级别的读写锁, 采用c++11 mutex封装实现

### TC\_ThreadCond

* 线程信号条件类，和TC\_ThreadMutex、TC\_ThreadRecMutex配合使用；
* 通常不直接使用，而是使用TC\_ThreadLock/TC\_ThreadRecLock;

### TC\_Monitor

* 线程锁监控模板类。
* 通常线程锁，都通过该类来使用，而不是直接用TC\_ThreadMutex、TC\_ThreadRecMutex。
* 该类将TC\_ThreadMutex/TC\_ThreadRecMutex 与TC\_ThreadCond结合起来；

定义了两个线程锁的模板：

```cpp
/**
 * 普通线程锁
 */
typedef TC_Monitor<TC_ThreadMutex, TC_ThreadCond> TC_ThreadLock;

/**
 * 循环锁(一个线程可以加多次锁)
 */
typedef TC_Monitor<TC_ThreadRecMutex, TC_ThreadCond> TC_ThreadRecLock;
```

在使用中，强烈建议使用：TC\_ThreadLock、TC\_ThreadRecLock；

关键成员函数说明：

* wait：当前调用线程在锁上等待，直到事件通知；
* timedWait：当前调用线程在锁上等待，直到超时或有事件通知；
* notify：通知等待在该锁上某一个线程醒过来，注意调用该函数时必须已经获得锁；
* notifyAll：通知等待在该锁上的所有线程醒过来，注意调用该函数时必须已经获得锁；

## 内存结构、文件映射类、数据结构类

### TC\_Bitmap

* 内存bitmap，每个整数1位；
* **可以支持多位，即几个整数多位；**
* 操作过程不加锁，如果有需要在外面调用的时候加，通常采用群锁策略；
* 注意群锁策略应该/8，然后按照尾号分群锁

```cpp
TC_Shm      g_shm;
TC_BitMap   g_bmap;
//计算4字节整型的bitmap需要多大内存
size_t iMemSize    = TC_BitMap::calcMemSize(uin32_t(-1));
//初始化共享内存
g_shm.init(iMemSize, 9999);
//创建bitmap
if (g_shm.iscreate())
{
    g_bmap.create(g_shm.getPointer(), g_shm.size());
}
else
{
    g_bmap.connect(g_shm.getPointer(), g_shm.size());
}
//获取某一个整型对应的一位，超出bitmap则返回－1
cout << "get:" << uin << "=" << g_bmap.get(uin) << endl;
//设置整型
cout << "set:" << uin << "=" << g_bmap.set(uin) << endl;
//清除整型
cout << "clear:" << uin << "=" << g_bmap.clear(uin) << endl;
//从dump到文件
int ret = g_bmap.dump2file(file);
//从文件load
int ret = g_bmap.load5file(file);
```

### TC\_Hashmap(注意, 不建议使用了!!!!)

* **内存hashmap，不要直接使用该类，通过jmem组件来使用，具体请参见11.3**
* 该hashmap通过TC\_MemMutilChunkAllocator来分配空间，支持不同大小的内存块的分配；
* 支持内存和共享内存；
* 对接口的所有操作都需要加锁；
* 内部有脏数据链，支持数据缓写；
* 当数据超过一个数据块时，则会拼接多个数据块；
* Set时当数据块用完，自动淘汰最长时间没有访问的数据，也可以不淘汰，直接返回错误；
* 支持dump到文件，或从文件load；

### TC\_HashmapCompact

* **紧凑性hashmap，使用方式同TC\_Hashmap，但是64位系统下更节约额外的管理空间；**
* **最大每个value的长度只能是64K(两个字节), 所以需要需要保存更大的数据, 建议使用TC\_Hashmap**

### TC\_RBTree

* **内存rbtree，不要直接使用该类，通过jmem组件来使用，具体请参见11.4**
* 该红黑树通过TC\_MemMutilChunkAllocator来分配空间，支持不同大小的内存块的分配；
* 分配器分配的是内存索引，减少自身消耗的空间（尤其是64位OS下面）；
* 支持内存和共享内存；
* 对接口的所有操作都需要加锁；
* 内部有脏数据链，支持数据缓写；
* 当数据超过一个数据块时，则会拼接多个数据块；
* Set时当数据块用完，自动淘汰最长时间没有访问的数据，也可以不淘汰，直接返回错误；
* 支持dump到文件，或从文件load；

### TC\_MemQueue

内存循环队列，建议不要直接使用该类，通过jmem组件来使用，具体参见11.2

```cpp
TC_Shm shm;
shm.init(8000, 1024);
TC_SemMutex  semLock;
semLock.init(8000);

TC_MemQueue memQueue;
//创建队列
if(shm.iscreate())
{
    memQueue.create(shm.getPointer(), 1024);
}
else
{
    memQueue.connect(shm.getPointer());
}

string sTest = “abc”;
//放入到队列尾部
memQueue.push(sTest);
//弹出数据
memQueue.pop(sTest);
```

### TC\_MemVector

* 基于内存的随机访问数据快模板类；
* 每个块大小相同；
* 模板对象只支持简单的数据类型，即类型支持bit-copy语义；

```cpp
struct tagTest
{
	char i;
	int n;
	float a[10];
} __attribute__((packed));
//__attribute__((packed))表示采用紧缩内存结构

TC_MemVector<tagTest> vt;
//计算总计内存空间
size_t is = TC_MemVector<tagTest>::calcMemSize(10);
char *buffer = new char[is];
//创建到对象
vt.create(buffer, is);
//链接到对象, vt.connect(buffer);
//获取对象0的对象
vt[0].i = ‘c’;
vt[0].n = 10;
delete []buffer;
```

### TC\_Mmap

* **文件内存映射类**；
* **linux/mac下使用mmap实现**
* **windows下使用文件映射内存实现**
* 封装了mmap的操作；

```cpp
TC_Mmap mmap;
//映射到文件，1024个字节
mmap.mmap("mmap.dat", 1024);
string s = “abc”;
//向文件copy数据，和内存操作完全一致；
memcpy(mmap.getPointer(), s.c_str(), s.length());
```

## 内存分配

### TC\_MemChunk

* 相同大小内存块类；
* 支持内存和共享内存；
* 每块内存至少4个字节；

### TC\_MemChunkAllocator

* 内存块分配器，提供分配和释放的功能；
* 只能分配相同大小的内存块；
* 每个内存块用TC\_MemChunk来管理；

### TC\_MemMultiChunkAllocator

* 内存块分配器，提供分配和释放的功能；
* 支持分配不同大小的内存块；
* 内部每种块用TC\_MemChunkAllocator来分配；
* 每种大小不同块的个数是相同的；

内存块分配的策略如下：

* 确定需要分配多大内存，假设需要分配A字节的内存；
* 分配大小大于>=A的内存块，优先分配大小最接近的；
* 如果都没有合适内存块，则分配大小\<A的内存块，优先分配大小最接近的；
* 如果仍然没有合适内存块，则返回NULL；

```cpp
char *buffer = new char[50240];
//定义分配器对象
TC_MemMultiChunkAllocator alloc;
//初始化，10：最小块大小，100：最大块大小，1.2：增长因子，表示块之间大小的增长比值		
alloc.create(buffer, 50240, 10, 100, 1.2);
vector<void*> v;
//定义需要分配的大小
size_t n = 10;
while(true)
{
    size_t iAllocSize;
    //分配空间，iAllocSize：真正分配的块大小
    void *p = alloc.allocate(n, iAllocSize);
    if(!p)
    {
        break;
    }
    v.push_back(p);
    n += 2;
}
//释放空间
for(size_t i = 0; i < v.size(); i++)
{
    alloc.deallocate(v[i]);
}
delete []buffer;
```

### TC\_Shm

* 共享内存管理类；
* 提供分配共享内存、连接共享内存、删除共享内存的功能；
* Linux/mac下用IPC的shm实现
* Windows下使用文件映射内存实现

```cpp
TC_Shm      g_shm;
size_t iMemSize = 10240;
g_shm.init(iMemSize, 9999);
if (g_shm.iscreate())
{
    //共享内存是创建的
        ;
}
else
{
    //共享内存是链接上的
;
}
//删除共享内存，类似ipcrm -M
g_shm.del();
```

### TC\_ThreadQueue

* 基于内存、STL容器的线程安全队列；
* 采用TC\_ThreadLock加解锁；

```cpp
//定义队列
TC_ThreadQueue<string> _queue;
//循环获取数据
while(true)
{
	//没有数据则等待10000ms
    if(_queue.pop_front(s, 10000))
    {
        cout << s << endl;
    }
    sleep(1);
}
while(true)
{
	//放入数据
    _queue.push_back(s);
    sleep(1);
}
//当程序退出时，如果线程仍然等待在pop_front上，则线程锁析够的时会有问题，此时需要用notifyT通知在pop_front上等待的线程醒过来
_queue.notifyT();
```

### TC\_TimeoutQueue

* 基于内存、STL容器的线程安全超时队列；
* 在如下场景中使用:
  * 需要当成map, 可以快速读写key-value数据;
  * 需要能够设置超时时间, 到点淘汰数据;

主要用于: 超时队列使用, 框架中也大量使用这个类

## 数据库类

### TC\_Mysql

* 提供mysql的操作类；
* **非线程安全，通常一个线程一个TC\_Mysql对象；**
* **对于insert/update可以有更好的函数封装，保证SQL注入；**
* TC\_Mysql::DB\_INT表示组装sql语句时，不加””和转义；
* TC\_Mysql::DB\_STR表示组装sql语句时，加””并转义；

```cpp
TC_Mysql mysql;
//初始化mysql，init时不链接，请求时自动建立链接；
//数据库可以为空；
//端口默认为3306
mysql.init("10.1.36.39", "pc", "pc@sn", "db_dmqq_system");
//获取链接的字符集
cout << mysql.getVariables("character_set_client") << endl;
//获取数据
TC_Mysql::MysqlData data;
data = mysql.queryRecord("select * from t_app_users");
for(size_t i = 0; i < data.size(); i++)
{
    //如果不存在ID字段，则抛出异常
    cout << data[i]["ID"] << endl;
}

//插入数据，指定数据的类型：数值 或 字符串，对于字符串会自动转义
map<string, pair<TC_Mysql::FT, string> > m;
m["ID"]     = make_pair(TC_Mysql::DB_INT, "2334");
m["USERID"] = make_pair(TC_Mysql::DB_STR, "abcttt");
m["APP"]    = make_pair(TC_Mysql::DB_STR, "abcapbbp");
m["LASTTIME"]    = make_pair(TC_Mysql::DB_INT, "now()");

//   mysql.insertRecord("t_user_logs", m);
mysql.replaceRecord("t_user_logs", m);
```

## 网络类

### TC\_Socket

* 提供socket的操作类；
* 支持tcp/udp socket；
* 支持本地域套接字；

```cpp
//获取本地的所有ip地址
vector<string> v = TC_Socket::getLocalHosts();
cout << TC_Common::tostr(v.begin(), v.end()) << endl;
```

### TC\_Epoller

提供网络epoll的操作类。

### TC\_Transceiver

提供网络连接的操作类, 具体使用请参考头文件。

### TC\_CoroutineScheduler

协程调度器.

### TC\_CoroutineQueue

协程调度队列.

用于跨线程的协程的数据交互, 队列没有数据时, 协程会阻塞在epoller上, 当有网络事件或者其他协程调度时会被唤醒处理其他事件!

### TC\_ClientSocket

提供客户端同步请求的socket类，用于发送数据包，支持tcp/udp，支持**大句柄**；

* 在TC\_Socket基础上实现；
* **多线程使用的时候，不用多线程同时send/recv，小心串包；**
* TC\_TCPClient：tcp的客户端类，socket句柄自动重连；
* TC\_UDPClient：udp的客户端类；
* TC\_TCPClient/TC\_UDPClient的发送或接收数据的返回值请参见TC\_ClientSocket::EM\_等枚举值；
* 初始化时指定：ip，port，超时时间（毫秒），注意对连接超时也处理了；
* 支持本地套接字，如果端口port是0表示是本地套接字，此时ip表示本地套接字的文件路径；

### TC\_TCPClient

* **多线程使用的时候，不用多线程同时send/recv，小心串包；**
* send：发送数据
* recv：接收数据
* recvLine：接收一行，即直到\r\n位置；
* recvAll：接收所有数据，直到服务器关闭链接；
* recvLength：接收指定长度的数据；
* sendRecv：发送并接收数据；
* sendRecvLine：发送并接收一行数据；
* sendRecvAll：发送并接收所有数据（直到服务器关闭链接）；

socket被关闭，会自动重新链接；

### TC\_UDPClient

* **多线程使用的时候，不用多线程同时send/recv，小心串包；**
* send：发送数据
* recv：接收数据
* recv：接收数据并返回远程的ip和端口
* sendRecv：发送并接收数据；
* sendRecv：发送并接收数据，同时返回远程ip和端口；

## 线程类

### TC\_Thread

线程基类，所有自定义线程继承于该类，同时实现run接口即可。可以通过TC\_ThreadContorl管理线程。

线程最大的问题就是如何正确的退出。通常一个线程在运行过程中，会做一些工作（比如从队列中获取数据执行计算），如果队列为空，就休息一会儿再执行，这里如果采用sleep来休息，则退出过程中，恰好在sleep，则必须等这时间之后才能退出。下面例子给出了如何正常退出一个线程的思路：

```cpp
class MyThread : public TC_Thread, public TC_ThreadLock
{
public:
    MyThread()
    {
        bTerminate = false;
    }
    /**
     * 结束线程
     */
    void terminate()
    {
		//先将退出标识设置为true
        bTerminate = true;
		
        {
			//加锁并通知线程醒过来
            TC_ThreadLock::Lock sync(*this);
            notifyAll();
        }
    }

    void doSomething()
    {
        cout << "doSomething" << endl;
    }
    /**
     * 运行
     */
protected:
    virtual void run() 
    {
        while(!bTerminate)
        {
             //TODO: your business
            doSomething();

			//做完工作以后，等待一下，注意在锁上等待，通知线程醒来的时候也是在锁上通知
            {
                TC_ThreadLock::Lock sync(*this);
                timedWait(1000);
            }
        }
    }

protected:
    bool bTerminate;
};

int main(int argc, char *argv[])
{
    try
    {
        MyThread mt;
        mt.start();

        sleep(5);
		
		//通知线程结束，并等待线程完全退出
        mt.terminate();
        mt.getThreadControl().join();
    }
    catch(exception &ex)
    {
        cout << ex.what() << endl;
    }

    return 0;
}
```

**说明：关键的思路就是采用线程锁来完成通知，保证线程正确、安全、及时的退出。**

### TC\_ThreadPool

* 线程池类；
* 需要和std::bind配合使用；
* 方便的多线程执行一个具体操作；

## 日志类

### TC\_Logger

* 日志模板类；
* 支持同步写、异步写；
* 线程安全的；
* 定义了TC\_DayLogger, TC\_RollLogger,通常直接使用这两个类即可；

## CGI类

### TC\_Cgi

* CGI解析类；
* 支持标准的HTTP解析；
* 支持Cookies；
* 支持多个文件的上传；

### TC\_Http

* Http协议解析类；
* 包括TC\_HttpRequest、TC\_HttpResponse两个类；
* 支持GET和POST，其他HTTP方法不支持；
* 通过TC\_HttpRequest::checkRequest判断http请求是否收完；
* 与TC\_ClientSocket配合，支持同步发送http请求，且支持http的chunk编码；
* 发送http请求时，非线程安全；

```cpp
 //定期http request对象
TC_HttpRequest stHttpReq;
stHttpReq.setCacheControl("no-cache");
//设置agent
stHttpReq.setUserAgent("TestAgent");
//设置请求地址和方式(GET方式请求)
stHttpReq.setRequest("http://www.qq.com", TC_HttpRequest::REQUEST_GET);
TC_HttpResponse stHttpRep;
//发送请求，并等待完整的HTTP响应，超时时间为10s
int iRet = stHttpReq.doRequest(stHttpRep, 10000);
if(iRet != 0)
{
    cout << iRet << endl;
}
//HTTP响应包的内容
cout << stHttpRep.getContent();
```

### TC\_HttpAsync

* Http协议异步请求类
* 支持ssl

### TC\_UUIDGenerator

* 单例
* 生成唯一的UUID

## 命令解析、配置文件类

### TC\_Config

* 配置文件解析类
* 支持从string中解析配置文件；
* **支持生成配置文件**；
* 解析出错抛出异常；
* 采用\[]获取配置，如果无配置则抛出异常；
* 采用get获取配置，不存在则返回空；
* **读取配置文件是线程安全的，insert域等函数非线程安全；**

例如：

```cpp
TC_Config conf;
//解析配置文件
conf.parseFile("./config.conf");
//输出配置文件格式
cout << conf.tostr() << endl;
//配置文件读入到内存
string s = TC_File::load2str("./config.conf");
//解析字符串
conf.parseString(s);
//读取root域下root字段，不存在则抛出异常
cout << conf["/root<root>"] << endl;
//读取root域下root字段，不存在则返回abc
cout << conf.get("/root<root>", “abc”) << endl;
//root/insert下插入insert子域，false：表示root/insert不存在时不创建
conf.insertDomain("/root/insert", "insert", false);		
map<string, string> m;
m["abc"] = "def";
m["ttt"] = "yyy";
//root/insert/insert下创建参数值对，false 表示/root/insert/insert不存在，则不创建
conf.insertDomainParam("/root/insert/insert", m, false);
//root/insert/insert下创建参数值对，true：表示自动创建
conf.insertDomainParam("/root/insert/insert", m, true);
cout << conf.tostr() << endl;
```

### TC\_Option

* 命令解析类；
* 通常用于解析命令行参数；
* 只支持双—的参数形式

分析main的输入参数，支持以下形式的参数：

./main.exe --name=value --param1 param2 param3

```cpp
 TC_Option op;
//解析命令行
op.decode(argc, argv);
//获取成对的参数，即获取 - - 表示的所有参数对
map<string, string> mp = op.getMulti();
//表示非 – 的参数：即 param2, param3
vector<string> d = op.getSingle();
```

如果value，param有空格或者--，用引号括起来就可以了。

## 智能指针类

### TC\_AutoPtr

* 智能指针模板类；
* 通过它定义智能指针；
* 该智能指针通过引用计数实现，可以放在容器中传递；
* 使用方式请参见：TC\_HandleBase
* 其实可以用c++11中shared\_ptr代替!!

### TC\_HandleBase

* 智能指针基类；
* 采用TC\_AutoPtr模板化的对象，必须都继承于该类；
* 内部采用引用计数std::atomic实现；
* 对象可以放在容器中；

例如：

```cpp
class TestAuto : public TC_HandleBase
{
    
};

Typedef TC_AutoPtr<TestAuto> TestAutoPtr;
```

## 其他类

### TC\_GZip

* Gzip压缩解压类, 需要连接zlib
* 仅仅支持linux/mac

### TC\_TimeProvider

* 时间获取类,获取毫秒/秒
* 不直接使用时间获取函数得到
* 背后有一个常驻线程, 通过计算cpu的频率来获取, 减少时间函数调用的用户内核态切换
* 建议需要获取时间的函数都通过这个类来得到

### TC\_Singleton(单例)

### TC\_Json

* Json解析类, 通常不直接使用
* Jce结构体都会生成json的对应函数
* 必要的时候可以使用

### TC\_Timer

* 定时器类
* 可以设置定事情, 并执行回调
* 可以设置回调的线程数
