高端网站制作建设,西安市建设网站,中级网页设计师,it运维管理系统一、c模板 c开发中#xff0c;在声明变量、函数、类时#xff0c;c都会要求使用指定的类型。在实际项目过程中#xff0c;会发现很多代码除了类型不同之外#xff0c;其他代码看起来都是相同的#xff0c;为了实现这些相同功能#xff0c;我们可能会进行如下设计#xf…一、c模板 c开发中在声明变量、函数、类时c都会要求使用指定的类型。在实际项目过程中会发现很多代码除了类型不同之外其他代码看起来都是相同的为了实现这些相同功能我们可能会进行如下设计
int max(const int v1, const int v2){return (v1v2)?v1:v2;
};
double max(const double v1, const double v2){return (v1v2)?v1:v2;
};
string max(const string v1, const string v2){return (v1v2)?v1:v2;
};
... 这明明针对相同行为的不同类型比较而已却一次又一次去重复实现它做了如此多重复的工作甚至还可能一不留神就引入更多错误开始一轮痛苦的调整之旅。而借助C的模板方法就可以更好地优化此类代码更好地利用c类型检查的特点更好格式的源代码。 目前模板的应用在c中非常广泛如在c标准库中几乎所有代码都是模板代码很多第三方c库也或多或少都会使用模板。模板编程是c开发中无可避免的一道坎。 模板是为多种类型而编写的函数和类这些类型都没有指定等在使用模板时再把类型作为一个显式或隐式的实参传递给模板完成具体场景化的应用。
二、函数模板 2.1 函数模板定义 函数模板提供类一种函数行为其可以用多种不同的类型进行调用一个函数模板就代表一个函数家族。前面提到比较两个数据的大小并返回较大值通过模板可以简化
//template class T //class 和 typename 没有区别
template typename T
T max(const T v1, const T v2)
{return (v1v2)?v1:v2;
}; 模板定义以关键字 template 开始后接模板形参表模板形参表是用尖括号括住的一个或多个模板形参的列表形参之间以逗号分隔模板形参表不能为空。这个模板定义指定一个“返回两个值中最大值”的家族函数参数类型还没确定采用模板参数T来替代参数列表是typename T。注意模板形参作用域和非模板形参的作用域是类似的这里就不展开阐述了。 在这里class T和 typename T是等价的鉴于历史原因可能会使用class取代typename来定义类型参数。在c语言发展演化过程中关键字typename 的出现相对较晚一些在它之前都是关键字class作为模板的类型参数引入的c也保留了下来。若要支持一些旧版本编译工具、库等就采用class否则建议使用关键字typename。但需要注意struct关键字是不行的不要因为class可行就产生误导了。 像函数形参一样程序员为模板形参选择的名字没有本质含义。将 max的模板类型形参命名为 T但也可以将它命名为任意名字:
template typename this_is_long_name
this_is_long_name max(const this_is_long_name v1, const this_is_long_name v2)
{return (v1v2)?v1:v2;
}; 2.2 模板调用 在使用模板时编译器会根据传入实参进行检测编译器会推断哪个或哪些模板实参绑定到模板形参。一旦编译器确定了实际的模板实参就称它实例化了函数模板的一个实例。实质上编译器将确定用什么类型代替每个类型形参以及用什么值代替每个非类型形参。推导出实际模板实参后编译器使用实参代替相应的模板形参产生编译该版本的函数。
maxint(14,16);
//编译器实质类似于
int max_int(const int v1, const int v2)
{return (v1v2)?v1:v2;
};max_int(14,16); 上述代码展示使用了int作为模板参数T的函数模板就会用具体类型替代模板参数这个过程就叫实例化它会产生一个模板实例。只要使用了函数模板编译器就会自动触发这样的一个实例化过程因此开发者并不需要额外地请求模板的实例化。 在使用函数模板时通过具体参数类型传递实参编译器就会明确参数类型其不允许自动类型转换每个模板参数都必须正确地匹配。 std::cout max(14,16) std::endl; //OKstd::cout maxint(14,16) std::endl; //OK,建议std::cout maxstd::string((nihao),(hi)) std::endl; //显式指定//std::cout max(nihao,hi) std::endl; //error,编译器无法明确//std::cout max(14,16.5) std::endl; //error,类型不匹配std::cout maxfloat(14,16.5) std::endl; //OK,显式指定std::cout max(static_castdouble(14),16.5) std::endl; //OK,强制类型转换 2.3 非类型模板形参 模板形参不必都是类型函数模板也可以使用的非类型形参。
template typename T, int LEN
void print(const T (val)[LEN])
{for(int i0; iLEN; i){std::cout val[i] std::endl;}
};//
std::string str[2] {hello,world};
print(str); //OK
printstd::string(str);//OK 2.4 模板声明和定义源码分离 模板的声明和定义一般都建议放置同一头文件内将声明和定义分离到头文件及源文件内c编译器会接受但连接器会出错。
/*test_template.h*/
#ifndef _TEST_TEMPLATE_H_
#define _TEST_TEMPLATE_H_//
template typename T
T min(const T v1, const T v2);#endif //_TEST_TEMPLATE_H_/*test_template.cpp*/
#include test_template.htemplate typename T
T min(const T v1, const T v2)
{return (v1v2)?v1:v2;
};/*test.cpp*/
#include test_template.h
int main(int argc, char* argv[])
{std::cout min(14,16) std::endl; return 0;
}; 编译时连接器会出错
ccZMcsD7.o:test.cpp:(.text0x207): undefined reference to int minint(int const, int const)
collect2.exe: error: ld returned 1 exit status 当然您也可以在头文件里包含源文件等同于模板的声明和定义一般都建议放置同一头文件内。
/*test_template.h*/
#ifndef _TEST_TEMPLATE_H_
#define _TEST_TEMPLATE_H_//
template typename T
T min(const T v1, const T v2);#include test_template.cpp //仅这里不同了哦-------------------
#endif //_TEST_TEMPLATE_H_
/*---------------------------------------------------*
/*test_template.cpp*/
#include test_template.htemplate typename T
T min(const T v1, const T v2)
{return (v1v2)?v1:v2;
};
/*---------------------------------------------------*
/*test.cpp*/
#include test_template.h
int main(int argc, char* argv[])
{std::cout min(14,16) std::endl; return 0;
}; 因此建议是模板的声明和定义都放置同一头文件内。
#ifndef _TEST_TEMPLATE_H_
#define _TEST_TEMPLATE_H_//
template typename T
T min(const T v1, const T v2);
{return (v1v2)?v1:v2;
};
#endif //_TEST_TEMPLATE_H_ 如果非要进行分离也是有办法就是较麻烦。另创建一个头文件放置模板函数的定义为了区别起名.hpp然后再创建一个头文件对模板函数进行显式实例化就可以避免链接期报错。
/*test_template.h*/
#ifndef _TEST_TEMPLATE_H_
#define _TEST_TEMPLATE_H_
//
template typename T
T min(const T v1, const T v2);#endif //_TEST_TEMPLATE_H_/*test_template.hpp*/
#ifndef _TEST_TEMPLATE_HPP_
#define _TEST_TEMPLATE_HPP_#include test_template.htemplate typename T
T min(const T v1, const T v2)
{return (v1v2)?v1:v2;
};#endif //_TEST_TEMPLATE_HPP_/*test_template.cpp*/
#include test_template.hpp
template int minint(const int v1, const int v2);
template double mindouble (const double v1, const double v2);/*test.cpp*/
#include test_template.h
int main(int argc, char* argv[])
{std::cout min(14,16) std::endl; //OK return 0;
}; 再编译时就可以通过。 另外如果您手头上的c编译器是支持export这个关键字特性的话做模板声明和定义分离编写会更容易。
/*test_template.h*/
#ifndef _TEST_TEMPLATE_H_
#define _TEST_TEMPLATE_H_
//
export template typename T
T min(const T v1, const T v2);#endif //_TEST_TEMPLATE_H_/*test_template.cpp*/
#include test_template.hexport template typename T
T min(const T v1, const T v2)
{return (v1v2)?v1:v2;
};/*test.cpp*/
#include test_template.h
int main(int argc, char* argv[])
{std::cout min(14,16) std::endl; //OK return 0;
}; 但是关于export这个关键字特性目前市面上支持的C编译器是较少的因此采用export时可能就通过宏定义编译条件了集合上述两种方法才能做到代码在各个编译器平滑支持了。 2.5 函数模板支持inline 另外函数模板可以用与非模板函数一样的方式声明为 inline。inline说明符放在模板形参表之后、返回类型之前不能放在关键字 template 之前。
template typename T inline T test(const T v1){return v1;}; //OK
inline template typename T T test(const T v1){return v1;}; //error 2.6 函数模板重载 和普通函数一样函数模板也可以被重载相同模板函数名称可具有不同函数定义当使用函数名称进行模板函数调用时编译器会根据调用语句进行检查推断调用匹配度更高的哪个候选模板函数。
template typename T
inline T max(const T v1, const T v2)
{return (v1v2)?v1:v2;
};template typename T
T max(const T v1, const T v2, const T v3)
{return max(max(v1,v2),v3);
};//
std::cout max(14,16,15) std::endl; //OK 但需要注意的是模板函数和普通函数重载时参数个数不一致是不行的
template typename T
inline T max(const T v1, const T v2)
{return (v1v2)?v1:v2;
};int max(const int v1){ return 0;} //编译错误multiple definition of max 但如果普通函数看着和模板函数函数名相同参数格式一致那就是模板函数的特例化实现。
template typename T
inline T max(const T v1, const T v2)
{return (v1v2)?v1:v2;
};inline char max(const char v1, const char v2)
{return (v1v2)?v1:v2;
};std::cout max(a,c) std::endl; //OK,大家认为会调用哪个函数呢如果第二个函数在前呢
std::cout maxchar(a,b) std::endl; 普通函数非模板函数和模板函数同名及参数格式一致时该模板函数可以被实例化为这个非模板函数在调用时编译器会根据重载解析过程调用匹配度更高的函数。在看看下面案例
template typename T
inline T max(const T v1, const T v2)
{return (v1v2)?v1:v2;
};template typename T
T max(const T v1, const T v2, const T v3)
{return max(max(v1,v2),v3); //使用模板函数,int的函数声明太迟了
};inline char max(const char v1, const char v2)
{return (v1v2)?v1:v2;
};std::cout max(a,b,c) std::endl; //OK,这个呢会调用那个函数两个参数的max
三、类模板 3.1 类模板定义 和函数一样类也可以被定义为模板像标准库中的容器就类模板它被用于管理某种特定类型的元素在使用它们时不需要确定容器中元素的类型。下面以本人曾定义过的一个类模板为例来唠叨一下类模板
/*queuedata.h*/
template class T
class QueueData
{
public:QueueData(std::string desc thread_queue);~QueueData();///*** 获取队列大小* return {int } 队列大小*/int size();/*** 判定队列是否为空* return {bool } 是否为空队列*/bool isEmpty();/*** 获取队列头元素* param it {T} 头元素* return {bool } 是否成功*/bool getFirst(T it);/*** 删除元素* return {bool } 是否成功*/bool removeFirst();/*** 获取队列头元素并从队列终删除* param it {T} 头元素* return {bool } 是否成功*/bool pop(T it);/*** 从队列头开始逐步获取多个元素并剔除* param its {queueT} 获取到的元素集* param sizel {int} 一次获取多少个* return {bool } 至少获取一个元素以上则成功*/bool getList(std::queueT its,unsigned int sizel5);/*** 从队列尾部添加元素* param it {T} 被添加元素* return {void } 无返回*/void add(T it);/*** 从队列头部添加元素* param it {T} 被添加元素* return {void } 无返回*/void add_front(T it);/*** 清空元素* return {void }*/void clear();
private:void init();QueueData operator(const QueueData) {return this;};
protected:std::string queue_desc;
private:/点集转发//协议解析结果缓存std::dequeT datacache_queue; //队列容器PYMutex m_Mutex; //线程锁,或者如果更彻底采用acl库,采用acl::thread_mutex替代//static unsigned int QSize; //队列大小约束,超出是会从队列头剔除旧数据腾出空位在对末添加数据//int queue_overS; //队列溢出次数计数
}; 类模板也是模板因此必须以关键字 template 开头后接模板形参表。QueueData模板接受一个名为 T 的模板类型形参。 除了模板形参表外类模板的定义看起来与任意其他类问相似。 类模板可以定义数据成员、函数成员和类型成员也可以使用访问标号控制对成员的访问还可以定义构造函数和析构函数等等。在类和类成员的定义中可以使用模板形参作为类型或值的占位符在使用类时再提供那些类型或值。 例如上述QueueData模板有一个模板类型形参可以在任何可以使用类型名字的地方使用该形参。在这个模板定义中用 T作为 add操作的形参类型。QueueData模板是基于标准库中的std::deque来实现的就不需要亲自实现内存管理、拷贝构造、赋值及算法等把精力聚焦在业务逻辑开发上。 和函数模板调用对比使用类模板时必须为模板形参显式指定实参。编译器使用实参来实例化这个类的特定类型版本,QueueData 不是类型而 QueueData int或 QueueData string 是类型。实质上编译器用用户提供的实际特定类型代替 T重新编写 QueueData类。
#include queuedata.hQueueDataint data1; //OK
//QueueData data2; //error
QueueDatastd::string data3; //OK 3.2 类模板的成员变量及成员函数 类模板的成员函数定义和函数模板分离时定义类似
//queuedata.h
template class T
void QueueDataT::init()
{queue_overS 0;
}; 采用模板参数T定义的成员变量也和普通类成员变量用法一致
template class T
class QueueData{
// 省略其他
private:std::dequeT datacache_queue; //队列容器
};template class T
void QueueDataT::add(T it)
{m_Mutex.Lock();if (datacache_queue.size() QSize) {queue_overS;datacache_queue.pop_front();}datacache_queue.push_back(it);m_Mutex.Unlock();if (queue_overS 10) {//每溢出10次报告一次printf(add item to queue %s at end,but the size of QueueData is up to limmit size: %d.\n, queue_desc.c_str(), QSize);queue_overS 0;}
} 对于static静态成员用法也一致,无非就是带上模板定义而已
template class T
class QueueData{
// 省略其他
private:static unsigned int QSize;//队列大小约束,超出是会从队列头剔除旧数据腾出空位在对末添加数据
};//
template class T
unsigned int QueueDataT::QSize 100; 3.3 类模板的特例化 类模板可以通过指定实参来特例化和函数模板的重载类似通过特化类模板通常是用来可以克服某种特定类型在实例化类模板时所出现的不足。
template
class QueueDatastd::string
{...
};
//相应地类模板特例化时每个成员函数必须都重新定义为普通函数模板参数T也被特例化类型取代。
int QueueDatastd::string::size()
{int ret 0;m_Mutex.Lock();ret static_castint(datacache_queue.size());m_Mutex.Unlock();return ret;
} 当类模板有多个模板参数时也可以进行局部特例化
template typename T1, typename T2
class TestData
{...
};
//局部特例化,两个模板参数相同
template typename T
class TestDataT,T
{...
};//局部特例化,第2模板参数int
template typename T
class TestDataT,int
{...
};
//局部特例化,两个模板参数改为指针
template typename T1, typename T2
class TestData*T1,*T2
{...
}; 3.4 非类型模板参数及缺省值 对于类模板还可以为模板参数定义缺省值。
templatetypename T, typename VALS std::vectorT
class TestData{private:VALS els;
}; 此外对于模板模板参数并不局限于类型普通值也可以作为模板参数可以给类模板指定类型及指定缺省值本专栏在讲述TCP/Socket通信代码优化时就用到过
#define RDC_SIZE 1024 //服务端从socket读取数据时的缓存大小
#define DATA_SIZE 512 //服务及客户端的数据传输(读取及写入)的缓存大小templateint SIZE DATA_SIZE
struct TCP_Data
{TCP_Data() : len(0){memset(Buf,0,SIZE);};...省略其他...unsigned char Buf[SIZE];int len;
};//调用
TCP_Data a; //大小512
TCP_DataDATA_SIZE a; //大小512 在这个例子里我们使用元素数目固定的数组来实现其优点就是避免内存开销让用户亲自制定数组的大小。当然这个例子极端了些再看看下面这个
templatetypename T, int MAXSIZE
class TCP_Data
{
public:TCP_Data();void doit();
private:int len;T els[MAXSIZE];
};
//定义成员函数
templatetypename T, int MAXSIZE
TCP_DataT,MAXSIZE::TCP_Data() : len(0)
{
};
//
templatetypename T, int MAXSIZE
void TCP_DataT,MAXSIZE::doit()
{
};//使用时同时制定模板参数类型和最大容量
TCP_Dataint,10 a;特别注意的是非类型模板参数是有限制的它们常整数包括枚举值或者指向外部链接对象的指针。
templatedouble VAT double doit(double val){}; //error
templatestd::string name class MyClass{}; //errortemplatechar const * name class MyClass{}; //error
char const* s hi;
MyClasss a; //error,指向内部链接对象extern char const s[] hi;
MyClasss a; //OK,指向外部链接对象
四、编译及附录代码 编译及运行输出 Makefile:
CX gGCC_CMD_DEF : 1
BIN : .
TARGET : test.exe
#FLAGS : -staticInclude : .
source : test.cpp Mutex.cpp test_template.cpp
#可以注释掉test_template.cpp 并在test_template.h的26行开启测试另一种伪分离的效果
$(TARGET) :$(CX) $(FLAGS) $(source) -I$(Include) -o $(BIN)/$(TARGET)clean:rm $(BIN)/$(TARGET) test_template.h
#ifndef _TEST_TEMPLATE_H_
#define _TEST_TEMPLATE_H_#include iostream
//template class T //class 和 typename 没有区别
template typename T
inline T max(const T v1, const T v2)
{return (v1v2)?v1:v2;
};template typename T
T max(const T v1, const T v2, const T v3)
{return max(max(v1,v2),v3);
};inline char max(const char v1, const char v2)
{return (v1v2)?v1:v2;
};//
template typename T
T min(const T v1, const T v2);
//#include test_template.hpp 开该项,就不需要test_template.cpp咯template typename T, int LEN
void print(const T (val)[LEN])
{for(int i0; iLEN; i){std::cout val[i] std::endl;}
};templatetypename T, int MAXSIZE
class TCP_Data
{
public:TCP_Data();~TCP_Data();void add(T const elem);void doit();
private:int len;T els[MAXSIZE];};
//定义成员函数
templatetypename T, int MAXSIZE
TCP_DataT,MAXSIZE::TCP_Data() : len(0)
{};templatetypename T, int MAXSIZE
TCP_DataT,MAXSIZE::~TCP_Data()
{
};templatetypename T, int MAXSIZE
void TCP_DataT,MAXSIZE::add(T const elem)
{if(lenMAXSIZE){//return;}els[len] elem;len;
};templatetypename T, int MAXSIZE
void TCP_DataT,MAXSIZE::doit()
{for(int i0; ilen; i){std::cout els[i] std::endl; //若T是自定义类型呢}
};#endif //_TEST_TEMPLATE_H_test_template.hpp
#ifndef _TEST_TEMPLATE_HPP_
#define _TEST_TEMPLATE_HPP_#include test_template.htemplate typename T
T min(const T v1, const T v2)
{return (v1v2)?v1:v2;
};#endif //_TEST_TEMPLATE_HPP_ test_template.cpp
#include test_template.hpptemplate int minint(const int v1, const int v2);
template double mindouble(const double v1, const double v2); test.cpp
#include iostream
#include test_template.h
#include queuedata.hint main(int argc, char* argv[])
{//模板调用std::cout max(14,16) std::endl; //OKstd::cout maxint(14,16) std::endl; //OK,建议std::cout maxstd::string((nihao),(hi)) std::endl; //显式指定//std::cout max(nihao,hi) std::endl; //error,编译器无法明确//std::cout max(14,16.5) std::endl; //error,类型不匹配std::cout maxfloat(14,16.5) std::endl; //OK,显式指定std::cout max(static_castdouble(14),16.5) std::endl; //OK,强制类型转换//std::string str[2] {hello,world};print(str); //OK printstd::string(str);//OK//分离声明及定义std::cout min(14,16) std::endl; //OK//重载std::cout max(14,16,15) std::endl; //OK//重载std::cout max(a,c) std::endl; //OKstd::cout maxchar(a,b) std::endl; //OKstd::cout max(a,b,c) std::endl; //OK//QueueDataint data1; //OK//QueueData data2; //errorQueueDatastd::string data3; //OKdata3.add(hi);data3.add_front(hello);std::string s_0;data3.getFirst(s_);std::cout first: s_ std::endl; //OK//TCP_Dataint,2 vals;vals.add(7);vals.add(17);vals.doit();return 0;
};queuedata.h
#if _MSC_VER 1000
#pragma once
#endif // _MSC_VER 1000#ifndef _QUEUE_DATA_H_
#define _QUEUE_DATA_H_/************************************************************************Copyright 2020-03-06, pyfree**File Name : queuedata.h*File Mark : *Summary : *数据队列类,线程安全**Current Version : 1.00*Author : pyfree*FinishDate :**Replace Version :*Author :*FinishDate :************************************************************************/
#include queue
#include deque
#include stdio.h
#include string.h#include Mutex.htemplate class T
class QueueData
{
public:QueueData(std::string desc thread_queue);~QueueData();///*** 获取队列大小* return {int } 队列大小*/int size();/*** 判定队列是否为空* return {bool } 是否为空队列*/bool isEmpty();/*** 获取队列头元素* param it {T} 头元素* return {bool } 是否成功*/bool getFirst(T it);/*** 删除元素* return {bool } 是否成功*/bool removeFirst();/*** 获取队列头元素并从队列终删除* param it {T} 头元素* return {bool } 是否成功*/bool pop(T it);/*** 从队列头开始逐步获取多个元素并剔除* param its {queueT} 获取到的元素集* param sizel {int} 一次获取多少个* return {bool } 至少获取一个元素以上则成功*/bool getList(std::queueT its,unsigned int sizel5);/*** 从队列尾部添加元素* param it {T} 被添加元素* return {void } 无返回*/void add(T it);/*** 从队列头部添加元素* param it {T} 被添加元素* return {void } 无返回*/void add_front(T it);/*** 清空元素* return {void }*/void clear();
private:void init();QueueData operator(const QueueData) {return this;};
protected:std::string queue_desc;
private:/点集转发//协议解析结果缓存std::dequeT datacache_queue; //队列容器PYMutex m_Mutex; //线程锁,或者如果更彻底采用acl库,采用acl::thread_mutex替代//static unsigned int QSize; //队列大小约束,超出是会从队列头剔除旧数据腾出空位在对末添加数据//int queue_overS; //队列溢出次数计数
};
template class T
unsigned int QueueDataT::QSize 100;template class T
QueueDataT::QueueData(std::string desc): queue_desc(desc)
{init();
};template class T
void QueueDataT::init()
{queue_overS 0;
};template class T
QueueDataT::~QueueData()
{}//
template class T
int QueueDataT::size()
{int ret 0;m_Mutex.Lock();ret static_castint(datacache_queue.size());m_Mutex.Unlock();return ret;
}template class T
bool QueueDataT::isEmpty()
{bool ret false;m_Mutex.Lock();ret datacache_queue.empty();m_Mutex.Unlock();return ret;
}template class T
bool QueueDataT::getFirst(T it)
{bool ret false;m_Mutex.Lock();if (!datacache_queue.empty()) {it datacache_queue.front();ret true;}m_Mutex.Unlock();return ret;
}template class T
bool QueueDataT::removeFirst()
{bool ret false;m_Mutex.Lock();if (!datacache_queue.empty()) {datacache_queue.pop_front();ret true;}m_Mutex.Unlock();return ret;
}template class T
bool QueueDataT::pop(T it)
{bool ret false;m_Mutex.Lock();if (!datacache_queue.empty()) {it datacache_queue.front();datacache_queue.pop_front();ret true;}m_Mutex.Unlock();return ret;
};template class T
bool QueueDataT::getList(std::queueT its,unsigned int sizel)
{m_Mutex.Lock();while (!datacache_queue.empty()){its.push(datacache_queue.front());datacache_queue.pop_front();if (its.size() sizel){break;}}m_Mutex.Unlock();return !its.empty();
};template class T
void QueueDataT::add(T it)
{m_Mutex.Lock();if (datacache_queue.size() QSize) {queue_overS;datacache_queue.pop_front();}datacache_queue.push_back(it);m_Mutex.Unlock();if (queue_overS 10) {//每溢出10次报告一次printf(add item to queue %s at end,but the size of QueueData is up to limmit size: %d.\n, queue_desc.c_str(), QSize);queue_overS 0;}
}template class T
void QueueDataT::add_front(T it)
{m_Mutex.Lock();if (datacache_queue.size() QSize) {queue_overS;datacache_queue.pop_front();}datacache_queue.push_front(it);m_Mutex.Unlock();if (queue_overS 10) {//每溢出10次报告一次printf(add item to queue %s at first,but the size of QueueData is up to limmit size: %d.\n, queue_desc.c_str(), QSize);queue_overS 0;}
}template class T
void QueueDataT::clear()
{m_Mutex.Lock();datacache_queue.clear();m_Mutex.Unlock();queue_overS 0;
}#endif //_QUEUE_DATA_H_Mutex.h
#if _MSC_VER 1000
#pragma once
#endif // _MSC_VER 1000#ifndef _PYMUTEX_H_
#define _PYMUTEX_H_/************************************************************************Copyright 2020-03-06, pyfree**File Name : Mutex.h*File Mark : *Summary : 线程锁**Current Version : 1.00*Author : pyfree*FinishDate :**Replace Version :*Author :*FinishDate :************************************************************************/#ifdef WIN32
//#include windows.h
#else
#include pthread.h
#endiftypedef void *HANDLE;class IMutex
{
public:virtual ~IMutex() {}/*** 上锁* return {void} */virtual void Lock() const 0;/*** 尝试上锁* return {void} */virtual bool TryLock() const 0;/*** 解锁* return {void} */virtual void Unlock() const 0;
};class PYMutex : public IMutex
{
public:PYMutex();~PYMutex();virtual void Lock() const;virtual bool TryLock() const;virtual void Unlock() const;
private:
#ifdef _WIN32HANDLE m_mutex;
#elsemutable pthread_mutex_t m_mutex;
#endif
};#endif //_PYMUTEX_H_Mutex.cpp
#include Mutex.h#ifdef WIN32
#include windows.h
#endif
//#include iostream
#include stdio.hPYMutex::PYMutex()
{
#ifdef _WIN32m_mutex ::CreateMutex(NULL, FALSE, NULL);
#elsepthread_mutex_init(m_mutex, NULL);
#endif
}PYMutex::~PYMutex()
{
#ifdef _WIN32::CloseHandle(m_mutex);
#elsepthread_mutex_destroy(m_mutex);
#endif
}void PYMutex::Lock() const
{
#ifdef _WIN32//DWORD d WaitForSingleObject(m_mutex, INFINITE);WaitForSingleObject(m_mutex, INFINITE);/// \todo check d for result
#elsepthread_mutex_lock(m_mutex);
#endif
}bool PYMutex::TryLock() const
{
#ifdef _WIN32DWORD dwWaitResult WaitForSingleObject(m_mutex, 0); if (dwWaitResult ! WAIT_OBJECT_0 dwWaitResult ! WAIT_TIMEOUT) {printf(thread WARNING: bad result from try-locking mutex\n);}return (dwWaitResult WAIT_OBJECT_0) ? true : false;
#elsereturn (0pthread_mutex_trylock(m_mutex))?true:false;
#endif
};void PYMutex::Unlock() const
{
#ifdef _WIN32::ReleaseMutex(m_mutex);
#elsepthread_mutex_unlock(m_mutex);
#endif
}