Skip to the content.

工具类说明(C++)

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

关于线程安全:

异常类

TC_Exception

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

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

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

帮助类

TC_Common

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

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

包括以下几种函数:

TC_File

文件相关的操作。

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

编解码、加密类

TC_Des

对于des加密:

对于3des加解密:

#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的编解码函数,通过静态函数提供。

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

TC_MD5

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

string src = test;
string hs = TC_MD5::md5str(src);
cout << hs << endl;

TC_Encoder

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

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

TC_Parsepara

锁类

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

TC_SemMutex

TC_LockT


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

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

TC_ThreadMutex

TC_ThreadRecMutex

TC_ThreadRWLock

TC_ThreadCond

TC_Monitor

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

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

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

在使用中,强烈建议使用:TC_ThreadLock、TC_ThreadRecLock;

关键成员函数说明:

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

TC_Bitmap

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(注意, 不建议使用了!!!!)

TC_HashmapCompact

TC_RBTree

TC_MemQueue

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

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

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

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

内存分配

TC_MemChunk

TC_MemChunkAllocator

TC_MemMultiChunkAllocator

内存块分配的策略如下:

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

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

//定义队列
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

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

数据库类

TC_Mysql

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

//获取本地的所有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_TCPClient

socket被关闭,会自动重新链接;

TC_UDPClient

线程类

TC_Thread

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

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

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

日志类

TC_Logger

CGI类

TC_Cgi

TC_Http

 //定期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

TC_UUIDGenerator

命令解析、配置文件类

TC_Config

例如:

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

 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

例如:

class TestAuto : public TC_HandleBase
{
    
};

Typedef TC_AutoPtr<TestAuto> TestAutoPtr;

其他类

TC_GZip

TC_TimeProvider

TC_Singleton(单例)

TC_Json

TC_Timer