//==================================tls.h=====================================================================
#if !defined(__TLS_H__)
#define __TLS_H__
#ifdef _MSC_VER
#include <wtypes.h>
#include <malloc.h>
typedef unsigned long tls_type;
#define ctid() ::GetCurrentThreadId()
#define mem_size(x) _msize(x)
#else
#include <pthread.h>
#include <malloc.h>
typedef pthread_key_t tls_type;
#define ctid() pthread_self()
#define mem_size(x) malloc_usable_size(x)
#endif
//中断应用
#define Breakpoint(T) { while (1) { printf("无效内存,程序中断...0x%08x...\r\n", (long)T); } }
class TlsIndex
{
public:
TlsIndex()
{
#ifdef _MSC_VER
m_index = TlsAlloc();
#else
pthread_key_create(&m_index, NULL);
#endif
}
~TlsIndex()
{
#ifdef _MSC_VER
::TlsFree(m_index);
#else
pthread_key_delete(m_index);
#endif
}
public:
operator tls_type() const
{
return m_index;
}
private:
tls_type m_index;
};
template<typename TDerived>
class TlsSingelton
{
typedef TDerived _Derived;
typedef TlsSingelton<TDerived> _Base;
public:
static _Derived* tlsInstance()
{
return tlsCreate();
}
protected:
static _Derived* tlsCreate()
{
_Derived* derived = tlsGet();
if ( derived )
return derived;
derived = new _Derived();
//printf("=============tlsCreate(0x%08x)=================\r\n\r\n", derived);
#ifdef _MSC_VER
TlsSetValue(tlsIndex(), derived);
#else
pthread_setspecific(tlsIndex(), derived);
#endif
return derived;
}
static bool tlsDestroy()
{
_Derived* derived = tlsGet();
if ( derived == NULL )
return false;
delete derived;
return true;
}
static tls_type tlsIndex()
{
static TlsIndex s_tlsIndex;
return s_tlsIndex;
}
private:
static _Derived* tlsGet()
{
#ifdef _MSC_VER
return reinterpret_cast<_Derived*>(::TlsGetValue(tlsIndex()));
#else
return reinterpret_cast<_Derived*>(pthread_getspecific(tlsIndex()));
#endif
}
//noncopyable
private:
TlsSingelton(const _Base&);
TlsSingelton& operator=(const _Base&);
};
#endif
//==============================================================tls_pools.h===================================
#if !defined(__TLS_POOLS__)
#define __TLS_POOLS__
#ifdef _MSC_VER
#pragma warning(disable: 4200)
#pragma warning(disable: 4786)
#pragma warning(disable: 4355 4244 4267 4311 4312)
#endif
#include <time.h>
#include <map>
#include <list>
#include <algorithm>
using namespace std;
#include "tls.h"
#include "zn_log.h"
#if (_MSC_VER >= 1300)
#include <hash_map>
using namespace stdext;
#elif defined(__GCC__) || defined(_GNUC)
#include <ext/hash_map>
using namespace __gnu_cxx;
#endif
#if defined(_USE_HASH_MAP)
#define mymap hash_map
#else
#define mymap std::map
#endif //_USE_HASH_MAP
namespace BaseLib {
const unsigned short buffer_mem_size = 512; //最小内存单位
const unsigned short buffer_reserved = 12; //预留字节数,前4位识别码后8位对像指针
const long max_granule = 0XF0000; //256K
inline int calculate_size(int nSize)
{
return nSize +
(buffer_mem_size - (nSize % buffer_mem_size)) + buffer_reserved;
}
class CMemory
{
typedef struct tick_
{
tick_() :utick(0) {}
unsigned long utick;
}_tick;
class Container
{
public:
typedef list<CMemory*> pool_list;
Container()
{
m_allpool = new pool_list;
m_idle = new pool_list;
}
pool_list* m_allpool;
pool_list* m_idle;
};
typedef mymap<unsigned long, Container*> MAP;
private:
CMemory(int nSize)
: m_allocate_size(nSize)
{
//printf("new size=%d\t", nSize);
//1.分配内存大小
m_pData = (unsigned char*)calloc(1, nSize);
//2.获取实际内存大小
long _size = mem_size(m_pData);
//3.写入内存标示
long* position = (long*)&m_pData[_size - buffer_reserved];
//保留字前4位为内存实际大小
(*position) = _size;
position++;
//保留字后4位为所在对象指针 TODO:64BIT 需要修改
(*position) = (const long)this;
m_nCrtThreadID = ctid();
m_nRefThreadID = 0;
}
~CMemory()
{
free(m_pData);
}
unsigned char* buffer()
{
return m_pData;
}
public:
static void* tls_malloc(unsigned long nSize, bool bCalculate = true) //分配内存
{
//1.获取TLS内存对像,不存在则创建
MAP* pMap = TlsSingelton<MAP>::tlsInstance();
if (pMap == NULL)
return NULL;
_tick* tick = TlsSingelton<_tick>::tlsInstance();
//===========================输出本线程内存块实用情况================================
if (time(0) - tick->utick > 120)
{
double total_size = 0.0;
for (MAP::iterator iter = pMap->begin(); iter != pMap->end(); ++iter)
{
c_znLog::_msg("线程ID=%8u, 块大小=%8d, 块数量=%8d, 空闲数量=%8d\r\n",
ctid(),
iter->first,
iter->second->m_allpool->size(),
iter->second->m_idle->size());
//计算总的分配的内存大小
total_size += (iter->second->m_allpool->size() * iter->first) / 1024.0;
}
c_znLog::_msg("线程ID=%8u, 分配内存总量 = %.4f MB\r\n", ctid(), total_size / 1024.0);
tick->utick = time(0);
}
//===========================30秒输出一次内存块的实用情况================================
//2.通过内存颗粒进行计算 如果传入参数bCalculate为false为不加入颗粒统计,只加预留字节buffer_reserved
int allocate_size = bCalculate ? calculate_size(nSize) : (nSize + buffer_reserved);
//3.分配内存大于内存池定义的最大颗粒而不参与内存池分配
if (allocate_size > max_granule)
{
Breakpoint(NULL);
return calloc(1, allocate_size);
}
CMemory* pResult = NULL;
Container* pContainer = NULL;
//4.查找当前颗粒内存对像列表
MAP::iterator iter = pMap->find(allocate_size);
if (iter != pMap->end())
{
pContainer = iter->second;
}
else
{
pContainer = new Container;
pMap->insert(make_pair(allocate_size, pContainer));
}
//5.检查其他线程是否有删除情况, 有就回收到空闲内存区中
if (!pContainer->m_allpool->empty())
{
pResult = pContainer->m_allpool->front();
//调整位置
pContainer->m_allpool->pop_front();
pContainer->m_allpool->push_back(pResult);
if (!pResult->IsDelete())
{
//如果正在使用
pResult = NULL;
}
else
{
//如果其他线程删除的内存把释放线程ID设置为0
pResult->m_nRefThreadID = 0;
}
}
//6.如果没有回收到内存
if (pResult == NULL)
{
if (!pContainer->m_idle->empty())
{
//从空闲内存区中取一块内存
pResult = pContainer->m_idle->front();
pContainer->m_idle->pop_front();
}
else
{
//如果还是没有可用内存则分配
pResult = new CMemory(allocate_size);
pContainer->m_allpool->push_back(pResult);
}
}
return pResult->buffer();
}
static void tls_free(void* T) //回收
{
//1.获取要释放内存大小
long _size = mem_size(T);
//2.效验内存是否通过内存池分配
long* position = (long*)&((const char*)T)[_size - buffer_reserved];
//3.效验内存大小不是否有效
if (*position != _size)
{
Breakpoint(T);
return;
}
//4.指向内存对像
++position;
CMemory* memory = (CMemory*)(*position);
memory->Release();
}
private:
//释放/回收
void Release()
{
//如果创建的线程与加收线程同一个直接回收
if (ctid() == m_nCrtThreadID)
{
//1.获取TLS内存对像,不存在则创建
MAP* pMap = TlsSingelton<MAP>::tlsInstance();
if (pMap == NULL)
return;
MAP::iterator iter = pMap->find(m_allocate_size);
if (iter != pMap->end())
{
Container* pContainer = iter->second;
pContainer->m_idle->push_back(this);
}
else
{
Breakpoint(m_pData);
}
}
else
{
m_nRefThreadID = ctid();
}
}
public:
bool IsDelete(void)
{
return m_nRefThreadID != 0 && m_nRefThreadID != m_nCrtThreadID;
}
public:
unsigned char* m_pData;
unsigned long m_allocate_size;
unsigned long m_nCrtThreadID; //创建时线程ID
unsigned long m_nRefThreadID; //删除时线程ID
};
//对象内存池
class CMPool
{
public:
void * operator new(size_t size) { return CMemory::tls_malloc(size, false); }
void operator delete (void * p) { CMemory::tls_free(p); }
};
//线程实例化
template<class T> class CTInstance
{
public:
CTInstance() {}
virtual ~CTInstance() {}
public:
static T* Allocate() { return TlsSingelton<T>::tlsInstance(); }
void Release() {}
};
}
//
//namespace new_op
//{
// inline void * operator new(size_t size)
// {
// return BaseLib::CMemory::tls_malloc(size);
// }
//
// inline void operator delete (void * p)
// {
// BaseLib::CMemory::tls_free(p);
// }
//
// inline void operator delete [] (void * p)
// {
// BaseLib::CMemory::tls_free(p);
// }
//}
#endif //__TLS_POOLS__
采用tls_malloc 分配内存 tls_free释放内存 支持多线程
服务器内存池专用