TKernel模块–杂项
1.DEFINE_HARRAY1
#define DEFINE_HARRAY1(HClassName, _Array1Type_) \
class HClassName : public _Array1Type_, public Standard_Transient { \
public: \
DEFINE_STANDARD_ALLOC \
DEFINE_NCOLLECTION_ALLOC \
HClassName () : _Array1Type_ () {} \
HClassName (const Standard_Integer theLower, \
const Standard_Integer theUpper) : \
_Array1Type_ (theLower,theUpper) {} \
HClassName (const Standard_Integer theLower, \
const Standard_Integer theUpper, \
const _Array1Type_::value_type& theValue) : \
_Array1Type_ (theLower,theUpper) { Init (theValue); } \
explicit HClassName (const typename _Array1Type_::value_type& theBegin, \
const Standard_Integer theLower, \
const Standard_Integer theUpper, \
const bool) : \
_Array1Type_ (theBegin,theLower,theUpper) {} \
HClassName (const _Array1Type_& theOther) : _Array1Type_(theOther) {} \
const _Array1Type_& Array1 () const { return *this; } \
_Array1Type_& ChangeArray1 () { return *this; } \
DEFINE_STANDARD_RTTI_INLINE(HClassName,Standard_Transient) \
}; \
DEFINE_STANDARD_HANDLE (HClassName, Standard_Transient)
#define IMPLEMENT_HARRAY1(HClassName)
看着是定义一个基于参数2的派生类,提供类似的功能。
2.DEFINE_HASHER
#define DEFINE_HASHER(HasherName, TheKeyType, HashFunctor, EqualFunctor) \
struct HasherName : protected HashFunctor, EqualFunctor \
{ \
size_t operator()(const TheKeyType& theKey) const noexcept \
{ \
return HashFunctor::operator()(theKey); \
} \
\
bool operator() (const TheKeyType& theK1, \
const TheKeyType& theK2) const noexcept \
{ \
return EqualFunctor::operator()(theK1, theK2); \
} \
};
集成取哈希值,键比较功能
3.DEFINE_HSEQUENCE
#define DEFINE_HSEQUENCE(HClassName, _SequenceType_) \
class HClassName : public _SequenceType_, public Standard_Transient { \
public: \
DEFINE_STANDARD_ALLOC \
DEFINE_NCOLLECTION_ALLOC \
HClassName () {} \
HClassName (const _SequenceType_& theOther) : _SequenceType_(theOther) {} \
const _SequenceType_& Sequence () const { return *this; } \
void Append (const _SequenceType_::value_type& theItem) { \
_SequenceType_::Append (theItem); \
} \
void Append (_SequenceType_& theSequence) { \
_SequenceType_::Append (theSequence); \
} \
_SequenceType_& ChangeSequence () { return *this; } \
template <class T> \
void Append (const Handle(T)& theOther, \
typename opencascade::std::enable_if<opencascade::std::is_base_of<HClassName, T>::value>::type * = 0) { \
_SequenceType_::Append (theOther->ChangeSequence()); \
} \
DEFINE_STANDARD_RTTI_INLINE(HClassName,Standard_Transient) \
}; \
DEFINE_STANDARD_HANDLE (HClassName, Standard_Transient)
#define IMPLEMENT_HSEQUENCE(HClassName)
为参数2提供派生类,提供类似功能
4.NCollection_Handle
template <class T>
class NCollection_Handle : public opencascade::handle<Standard_Transient> {
private:
class Ptr : public Standard_Transient {
public:
Ptr (T* theObj) : myPtr (theObj) {}
~Ptr () { if ( myPtr ) delete myPtr; myPtr = 0; }
protected:
Ptr(const Ptr&);
Ptr& operator=(const Ptr&);
public:
T* myPtr;
};
NCollection_Handle (Ptr* thePtr, int) : opencascade::handle<Standard_Transient> (thePtr) {}
public:
typedef T element_type;
NCollection_Handle () {}
NCollection_Handle (T* theObject) : opencascade::handle<Standard_Transient> (theObject ? new Ptr (theObject) : 0) {}
T* get () { return ((Ptr*)opencascade::handle<Standard_Transient>::get())->myPtr; }
const T* get () const { return ((Ptr*)opencascade::handle<Standard_Transient>::get())->myPtr; }
T* operator -> () { return get(); }
const T* operator -> () const { return get(); }
T& operator * () { return *get(); }
const T& operator * () const { return *get(); }
static NCollection_Handle<T> DownCast (const opencascade::handle<Standard_Transient>& theOther) {
return NCollection_Handle<T>(dynamic_cast<Ptr*>(theOther.get()), 0);
}
};
做的还是为原始指针做包装。opencascade::handle<Standard_Transient>已经是一层包装,为原始指针加引用计数管理。这里本质还是在包装。
5.NCollection_Shared
template <class T, typename = typename opencascade::std::enable_if<! opencascade::std::is_base_of<Standard_Transient, T>::value>::type>
class NCollection_Shared : public Standard_Transient, public T {
public:
DEFINE_STANDARD_ALLOC
DEFINE_NCOLLECTION_ALLOC
NCollection_Shared () {}
template<typename T1> NCollection_Shared (const T1& arg1) : T(arg1) {}
template<typename T1> NCollection_Shared (T1& arg1) : T(arg1) {}
template<typename T1, typename T2> NCollection_Shared (const T1& arg1, const T2& arg2) : T(arg1, arg2) {}
template<typename T1, typename T2> NCollection_Shared (T1& arg1, const T2& arg2) : T(arg1, arg2) {}
template<typename T1, typename T2> NCollection_Shared (const T1& arg1, T2& arg2) : T(arg1, arg2) {}
template<typename T1, typename T2> NCollection_Shared (T1& arg1, T2& arg2) : T(arg1, arg2) {}
};
NCollection_Shared 是 OpenCASCADE (OCCT) 中的一个模板类,它提供了一种将非继承自 Standard_Transient 的类包装成可共享对象的方式。
这个类的主要目的是让那些原本不继承 Standard_Transient 的类能够获得引用计数和自动内存管理的功能。这在需要共享对象所有权的情况下非常有用。
6.Standard_MMgrRoot
class Standard_MMgrRoot {
public:
Standard_EXPORT virtual ~Standard_MMgrRoot(){}
Standard_EXPORT virtual Standard_Address Allocate (const Standard_Size theSize)=0;
Standard_EXPORT virtual Standard_Address Reallocate (Standard_Address thePtr, const Standard_Size theSize)=0;
Standard_EXPORT virtual void Free(Standard_Address thePtr)=0;
Standard_EXPORT virtual Standard_Integer Purge(Standard_Boolean isDestroyed=Standard_False){
return 0;
}
};
7.Standard_MMgrOpt
if defined(__linux__)
#define MMAP_BASE_ADDRESS 0x20000000
#define MMAP_FLAGS (MAP_PRIVATE)
end
// 将给定的尺寸向上对齐到页面尺寸倍数
#define PAGE_ALIGN(size,thePageSize) \
(((size) + (thePageSize) - 1) & ~((thePageSize) - 1))
// 将给定的尺寸向上对齐到16的倍数
#define ROUNDUP16(size) (((size) + 0xf) & ~(Standard_Size)0xf)
// 将给定的尺寸向上对齐到8的倍数
#define ROUNDUP8(size) (((size) + 0x7) & ~(Standard_Size)0x7)
// 将给定的尺寸向上对齐到4的倍数
#define ROUNDUP4(size) (((size) + 0x3) & ~(Standard_Size)0x3)
// 将给定的尺寸向下对齐到8的倍数
#define ROUNDDOWN8(size) ((size) & ~(Standard_Size)0x7)
// 将给定的尺寸向上对齐到8的倍数
#define ROUNDUP_CELL(size) ROUNDUP8(size)
// 将给定的尺寸向下对齐到8的倍数
#define ROUNDDOWN_CELL(size) ROUNDDOWN8(size)
// 给定尺寸,计算其被8所除的结果整数部分
#define INDEX_CELL(rsize) ((rsize) >> 3)
#define BLOCK_SHIFT 1
// 前进一个Standard_Size大小,从块地址得到可用内存地址
#define GET_USER(block) (((Standard_Size*)(block)) + BLOCK_SHIFT)
// 后退一个Standard_Size大小,从可用内存地址得到块地址
#define GET_BLOCK(storage) (((Standard_Size*)(storage))-BLOCK_SHIFT)
class Standard_MMgrOpt : public Standard_MMgrRoot {
protected:
Standard_Boolean myClear;
Standard_Size myFreeListMax;
Standard_Size ** myFreeList;
Standard_Size myCellSize;
Standard_Integer myNbPages;
Standard_Size myPageSize;
Standard_Size * myAllocList;
Standard_Size * myNextAddr;
Standard_Size * myEndBlock;
Standard_Integer myMMap;
Standard_Size myThreshold;
Standard_Mutex myMutex;
Standard_Mutex myMutexPools;
public:
Standard_EXPORT Standard_MMgrOpt(const Standard_Boolean aClear = Standard_True,
const Standard_Boolean aMMap = Standard_True, const Standard_Size aCellSize = 200,
const Standard_Integer aNbPages = 10000, const Standard_Size aThreshold = 40000){
Standard_STATIC_ASSERT(sizeof(Standard_Size) == sizeof(Standard_Address));
myFreeListMax = 0;
myFreeList = NULL;
myPageSize = 0;
myAllocList = NULL;
myNextAddr = NULL;
myEndBlock = NULL;
myClear = aClear;
myMMap = (Standard_Integer)aMMap;
myCellSize = aCellSize;
myNbPages = aNbPages;
myThreshold = aThreshold;
Initialize();
}
protected:
Standard_EXPORT void Initialize(){
if ( myNbPages < 100 )
myNbPages = 1000;
#ifndef _WIN32
myPageSize = getpagesize();
if ( ! myPageSize )
myMMap = 0;
#else
SYSTEM_INFO SystemInfo;
GetSystemInfo (&SystemInfo);
myPageSize = SystemInfo.dwPageSize;
#endif
if(myMMap) {
myMMap = -1;
}
myFreeListMax = INDEX_CELL(ROUNDUP_CELL(myThreshold-BLOCK_SHIFT)); // all blocks less than myThreshold are to be recycled
// 每个链表负责维护固定尺寸内存块分配和回收?
// 链表负责的内存块尺寸以8为刻度递增
myFreeList = (Standard_Size **) calloc (myFreeListMax+1, sizeof(Standard_Size *));
myCellSize = ROUNDUP16(myCellSize);
}
public:
Standard_EXPORT virtual Standard_Integer Purge(Standard_Boolean isDestroyed){
Standard_Mutex::Sentry aSentry (myMutex);
Standard_Integer nbFreed = 0;
// 快速定位到myCellSize尺寸最低可分配的链表索引
Standard_Size i = INDEX_CELL(ROUNDUP_CELL(myCellSize+BLOCK_SHIFT));
// 从该链表到后续各个链表内所有块依次释放
for (; i <= myFreeListMax; i++ ) {
// 获得链表首个块地址
Standard_Size * aFree = myFreeList[i];
while(aFree) {
// 保存当前块地址
Standard_Size * anOther = aFree;
// 移动到下一个块。能如此的原因:每个内存块首个位置存放下一个块的地址。
aFree = * (Standard_Size **) aFree;
// 释放块
free(anOther);
nbFreed++;
}
// 释放后链表置空
myFreeList[i] = NULL;
}
Standard_Mutex::Sentry aSentry1 (myMutexPools);
#ifndef _WIN32
const Standard_Size PoolSize = myPageSize * myNbPages;
#else
// 内存池大小
const Standard_Size PoolSize = PAGE_ALIGN(myPageSize * myNbPages + sizeof(HANDLE), myPageSize) - sizeof(HANDLE);
#endif
// 向下规整
const Standard_Size RPoolSize = ROUNDDOWN_CELL(PoolSize);
// 一个池可容纳的Standard_Size对象个数
const Standard_Size PoolSizeN = RPoolSize / sizeof(Standard_Size);
static const Standard_Integer NB_POOLS_WIN = 512;
static Standard_Size* aPools[NB_POOLS_WIN];
static Standard_Size aFreeSize[NB_POOLS_WIN];
static Standard_Integer aFreePools[NB_POOLS_WIN];
Standard_Size * aNextPool = myAllocList;
Standard_Size * aPrevPool = NULL;
// 给定尺寸得到此尺寸的索引
const Standard_Size nCells = INDEX_CELL(myCellSize);
Standard_Integer nPool = 0, nPoolFreed = 0;
// 每个内存块作为一个Pool?
while (aNextPool) {
Standard_Integer iPool;
for (iPool = 0; aNextPool && iPool < NB_POOLS_WIN; iPool++) {
aPools[iPool] = aNextPool;
aFreeSize[iPool] = 0;
aNextPool = * (Standard_Size **) aNextPool; // get next pool
}
const Standard_Integer iLast = iPool - 1;
(void )nPool; // unused but set for debug
nPool += iPool;// 块的个数
// 完成小块链表释放
for (i = 0; i <= nCells; i++ ) {
// 负责小块内存分配的块列表
Standard_Size * aFree = myFreeList[i];
Standard_Size aSize = BLOCK_SHIFT * sizeof(Standard_Size) + ROUNDUP_CELL(1) * i;
while(aFree) {
for (iPool = 0; iPool <= iLast; iPool++) {
// 若是此个地址块落在内存池块内
if (aFree >= aPools[iPool] && aFree < aPools[iPool] + PoolSizeN) {
aFreeSize[iPool] += aSize;// 此内存池块内可分配内存增加
break;
}
}
aFree = * (Standard_Size **) aFree; // 继续前进到链表下一个小块
}
}
Standard_Integer iLastFree = -1;
for (iPool = 0; iPool <= iLast; iPool++) {
// 可分配尺寸向上对齐
aFreeSize[iPool] = ROUNDUP_CELL(aFreeSize[iPool]);
if (aFreeSize[iPool] == RPoolSize)
aFreePools[++iLastFree] = iPool;// 得到一个完全空闲的快池
}
if (iLastFree == -1) {// 无法得到一个完全空闲的块池
aPrevPool = aPools[iLast];
continue;
}
Standard_Integer j;
for (i = 0; i <= nCells; i++ ) {
Standard_Size * aFree = myFreeList[i];
Standard_Size * aPrevFree = NULL;
while(aFree) {
// 若小块落在完全空闲块池
for (j = 0; j <= iLastFree; j++) {
iPool = aFreePools[j];
if (aFree >= aPools[iPool] && aFree < aPools[iPool] + PoolSizeN)
break;
}
if (j <= iLastFree) {// 表示小块落在完全空闲块池
// 将此小块从链表移除
aFree = * (Standard_Size **) aFree;
if (aPrevFree)
* (Standard_Size **) aPrevFree = aFree;
else
myFreeList[i] = aFree;
nbFreed++;
}
else {// 表示小块未落在完全空闲块池
aPrevFree = aFree;// 取得小块地址
aFree = * (Standard_Size **) aFree;// 继续分析下一个小块
}
}
}
Standard_Size * aPrev = (aFreePools[0] == 0 ? aPrevPool : aPools[aFreePools[0] - 1]);
for (j = 0; j <= iLastFree; j++) {
iPool = aFreePools[j];
if (j > 0) {
if (iPool - aFreePools[j - 1] > 1)
aPrev = aPools[iPool - 1];
}
if (j == iLastFree || aFreePools[j + 1] - iPool > 1) {
Standard_Size * aNext = (j == iLastFree && aFreePools[j] == iLast) ? aNextPool : aPools[iPool + 1];
if (aPrev)
* (Standard_Size **) aPrev = aNext;
else
myAllocList = aNext;
}
FreeMemory(aPools[iPool], PoolSize);
}
aPrevPool = (aFreePools[iLastFree] == iLast ? aPrev : aPools[iLast]);
(void )nPoolFreed; // unused but set for debug
nPoolFreed += iLastFree + 1;
}
return nbFreed;
}
void FreeMemory (Standard_Address aPtr, const Standard_Size aSize){
if ( myMMap ) {
#ifndef _WIN32
const Standard_Size AlignedSize = PAGE_ALIGN(aSize, myPageSize);
munmap((char*)aBlock, AlignedSize);
#else
const HANDLE * aMBlock = (const HANDLE *)aBlock;
HANDLE hMap = *(--aMBlock);
UnmapViewOfFile((LPCVOID)aMBlock);
CloseHandle (hMap);
#endif
}
else
free(aBlock);
}
void FreePools(){
Standard_Mutex::Sentry aSentry (myMutexPools);
Standard_Size * aFree = myAllocList;
myAllocList = 0;
while (aFree) {
Standard_Size * aBlock = aFree;
aFree = * (Standard_Size **) aFree;
FreeMemory ( aBlock, myPageSize * myNbPages );
}
}
Standard_EXPORT virtual ~Standard_MMgrOpt(){
Purge(Standard_True);
free(myFreeList);
FreePools();
}
public:
// 分析内存分配实现策略
Standard_EXPORT virtual Standard_Address Allocate(const Standard_Size aSize){
Standard_Size * aStorage = NULL;
// 尺寸向上对齐到倍数
volatile Standard_Size RoundSize = ROUNDUP_CELL(aSize);
// 可以满足此尺寸的最小索引
const Standard_Size Index = INDEX_CELL(RoundSize);
// 这里弄了个myFreeListMax这个概念。多级链表,由不同尺寸内存块构成的链表。
// myFreeListMax这个概念用于实现小块内存的回收复用。从而避免小块内存分配时执行系统调用malloc/free,提升性能
// 系统调用涉及内核态用户态转换,上下文恢复较纯应用层调用耗时会更多
if ( Index <= myFreeListMax ) {
// 对齐后尺寸能容纳的Standard_Size对象个数
const Standard_Size RoundSizeN = RoundSize / sizeof(Standard_Size);
// 核心分配过程做了互斥保护
myMutex.Lock();
// 定位到的链表是否有元素
if ( myFreeList[Index] ) {
// 取得链表首个元素地址
Standard_Size* aBlock = myFreeList[Index];
// 将首个元素分配出去,更新链表首个元素地址
myFreeList[Index] = *(Standard_Size**)aBlock;
myMutex.Unlock();
// 基类分配到的内存块尺寸
aBlock[0] = RoundSize;
// 从块地址得到可用内存地址
aStorage = GET_USER(aBlock);
if (myClear)
memset (aStorage, 0, RoundSize);// 内存部分需要清理
}
// 对应的小块链表为孔,且对齐后尺寸不超过myCellSize
else if ( RoundSize <= myCellSize ) {
myMutex.Unlock();
// 这里使用多个锁,实现细粒度的互斥保护,有利于提升并发性能。
Standard_Mutex::Sentry aSentry (myMutexPools);
// myNextAddr,myEndBlock机制
// 在多级小块内存复用链表机制外,对于较小尺寸内存的分配额外引用直接分配机制。
// 提供一个较大块,当较小块分配时,定位到其复用块链表为空时,尝试从此较大块直接分配出一个小块。
Standard_Size *aBlock = myNextAddr;
// 当大块剩余部分不足完成本次分配
if ( &aBlock[ BLOCK_SHIFT+RoundSizeN] > myEndBlock ) {
// 进入到这里是发现此较大块剩余部分不足完成本次分配。
// 采取的策略是重新分配一个较大块
Standard_Size Size = myPageSize * myNbPages;
aBlock = AllocMemory(Size);
// 若当前较大块剩余部分尚有内存空间可供分配
if (myEndBlock > myNextAddr) {
// 剩余部分中可用内存尺寸
const Standard_Size aPSize = (myEndBlock - GET_USER(myNextAddr)) * sizeof(Standard_Size);
// 内存尺寸向下对齐
const Standard_Size aRPSize = ROUNDDOWN_CELL(aPSize);
// 内存尺寸对应的多级小块链表索引
const Standard_Size aPIndex = INDEX_CELL(aRPSize);
// 若此索引属于合法索引范围
if ( aPIndex > 0 && aPIndex <= myFreeListMax ) {
myMutex.Lock();
// 头插法加入到对应小块链表
// 这里的一个灵活多变。
// 大尺寸块可分分割为多个小尺寸块。
// 大尺寸块的结构是:
// 4字节下一个大尺寸块地址+多个小尺寸块
// 小尺寸块结构是:
// 头4字节+可用内存区域
// 在小尺寸块位于回收链表时,其头4字节指向链表下一个小尺寸块的地址
// 在小尺寸块被分配出去时,其头4字节存储了此块内已经分配内存尺寸。
*(Standard_Size**)myNextAddr = myFreeList[aPIndex];
myFreeList[aPIndex] = myNextAddr;
myMutex.Unlock();
}
}
// 计算新块的结束位置
myEndBlock = aBlock + Size / sizeof(Standard_Size);
// 将新的较大块加入myAllocList链表
// myAllocList机制:由较大块构成的分配链表。
*(Standard_Size**)aBlock = myAllocList;
myAllocList = aBlock;
// 原始块的布局:
// 4字节为下一个块的地址+4字节为本块已经分配出去内存尺寸+可用内存区域
aBlock+=BLOCK_SHIFT;
}
// 记录本块内已经分配内存尺寸
aBlock[0] = RoundSize;
// 从块得到可用内存区域地址
aStorage = GET_USER(aBlock);
// 下一个可供分配的地址
myNextAddr = &aStorage[RoundSizeN];
}
// 对应的小块链表为孔,且对齐后尺寸超过myCellSize。
// myCellSize属于中尺寸和大尺寸分界线。
else {
myMutex.Unlock();
// 这里相当于处理大尺寸块的分配
// 直接通过系统api完成分配
Standard_Size *aBlock =
(Standard_Size*) (myClear ? calloc( RoundSizeN+BLOCK_SHIFT, sizeof(Standard_Size))
: malloc((RoundSizeN+BLOCK_SHIFT) * sizeof(Standard_Size)) );
// 直到无法完成分配时,才执行清理,释放多余空闲内存。
// 清理的时机有点晚了。
if ( ! aBlock ) {
if ( Purge (Standard_False) )
aBlock = (Standard_Size*)calloc(RoundSizeN+BLOCK_SHIFT, sizeof(Standard_Size));
if ( ! aBlock )
throw Standard_OutOfMemory("Standard_MMgrOpt::Allocate(): malloc failed");
}
// 直接分配的大尺寸块的结构:
// 4字节存储块中已经分配内存尺寸+可用内存区域
aBlock[0] = RoundSize;
// 可用内存区域指针
aStorage = GET_USER(aBlock);
}
}
// 索引直接超过了myFreeListMax,属于超大块了。
// myFreeListMax构成了大块和超大块的分水岭。
else {
Standard_Size AllocSize = RoundSize + sizeof(Standard_Size);
// 通过AllocMemory完成超大快的分配
Standard_Size* aBlock = AllocMemory(AllocSize);
aBlock[0] = RoundSize;
aStorage = GET_USER(aBlock);
}
// 每次分配成功都触发一次回调。参数3是对齐后尺寸,参数4是原始尺寸。
callBack(Standard_True, aStorage, RoundSize, aSize);
return aStorage;
}
// 释放+重新分配
Standard_EXPORT virtual Standard_Address Reallocate (Standard_Address theStorage, const Standard_Size theNewSize){
if (!theStorage) {
return Allocate(theNewSize);
}
// 得到块起始地址
Standard_Size * aBlock = GET_BLOCK(theStorage);
Standard_Address newStorage = NULL;
// 块内已经使用内存尺寸
Standard_Size OldSize = aBlock[0];
if (theNewSize <= OldSize) {
// 复用
newStorage = theStorage;
}
else {
newStorage = Allocate(theNewSize);
memcpy (newStorage, theStorage, OldSize);
Free( theStorage );
if ( myClear )
memset(((char*)newStorage) + OldSize, 0, theNewSize-OldSize);
}
return newStorage;
}
Standard_EXPORT virtual void Free (Standard_Address thePtr){
if ( ! theStorage )
return;
Standard_Size* aBlock = GET_BLOCK(theStorage);
Standard_Size RoundSize = aBlock[0];
// 释放时也触发回调
callBack(Standard_False, theStorage, RoundSize, 0);
const Standard_Size Index = INDEX_CELL(RoundSize);
if ( Index <= myFreeListMax ) {
myMutex.Lock();
// 头插法加入链表
*(Standard_Size**)aBlock = myFreeList[Index];
myFreeList[Index] = aBlock;
myMutex.Unlock();
}
else
FreeMemory (aBlock, RoundSize);// 直接释放
}
typedef void (*TPCallBackFunc)(const Standard_Boolean theIsAlloc, const Standard_Address theStorage, const Standard_Size theRoundSize, const Standard_Size theSize);
Standard_EXPORT static void SetCallBackFunction(TPCallBackFunc pFunc);
// 内存分配
Standard_Size* AllocMemory (Standard_Size &aSize){
retry:
Standard_Size * aBlock = NULL;
// 使用内存映射完成分配
if (myMMap) {
#ifndef _WIN32
const Standard_Size AlignedSize = PAGE_ALIGN(Size, myPageSize);
aBlock = (Standard_Size * )mmap((char*)MMAP_BASE_ADDRESS, AlignedSize, PROT_READ | PROT_WRITE, MMAP_FLAGS, myMMap, 0);
if (aBlock == MAP_FAILED /* -1 */) {
int errcode = errno;
if ( Purge(Standard_False) )
goto retry;
throw Standard_OutOfMemory(strerror(errcode));
}
Size = AlignedSize;
#else /* _WIN32 */
const Standard_Size AlignedSize = PAGE_ALIGN(Size+sizeof(HANDLE), myPageSize);
// 内存映射得到内存
HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, DWORD(AlignedSize / 0x80000000), DWORD(AlignedSize % 0x80000000), NULL);
// 获得句柄
HANDLE * aMBlock = (hMap && GetLastError() != ERROR_ALREADY_EXISTS ?
(HANDLE*)MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0) : NULL);
if ( ! aMBlock ) {
if ( hMap )
CloseHandle(hMap);
hMap = 0;
// 无法完成分配时先清理再次尝试
if ( Purge(Standard_False) )
goto retry;
const int BUFSIZE=1024;
wchar_t message[BUFSIZE];
if ( FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, message, BUFSIZE-1, 0) <=0 )
StringCchCopyW(message, _countof(message), L"Standard_MMgrOpt::AllocMemory() failed to mmap");
char messageA[BUFSIZE];
WideCharToMultiByte(CP_UTF8, 0, message, -1, messageA, sizeof(messageA), NULL, NULL);
throw Standard_OutOfMemory(messageA);
}
// 一开始存储hMap
aMBlock[0] = hMap;
// 块有效区域
aBlock = (Standard_Size*)(aMBlock+1);
// 有效区域尺寸
Size = AlignedSize - sizeof(HANDLE);
#endif
}
else {
// 使用api完成分配
aBlock = (Standard_Size *) (myClear ? calloc(Size,sizeof(char)) : malloc(Size));
if ( ! aBlock ) {
if ( Purge(Standard_False) )
goto retry;
throw Standard_OutOfMemory("Standard_MMgrOpt::Allocate(): malloc failed");
}
}
if (myClear)
memset (aBlock, 0, Size);
return aBlock;
}
};
// 源文件
static Standard_MMgrOpt::TPCallBackFunc MyPCallBackFunc = NULL;
Standard_EXPORT void Standard_MMgrOpt::SetCallBackFunction(TPCallBackFunc pFunc) {
MyPCallBackFunc = pFunc;
}
inline void callBack(const Standard_Boolean isAlloc,
const Standard_Address aStorage, const Standard_Size aRoundSize, const Standard_Size aSize) {
if (MyPCallBackFunc)
(*MyPCallBackFunc)(isAlloc, aStorage, aRoundSize, aSize);
}
8.Standard_Persistent
class Standard_Persistent : public Standard_Transient {
public:
DEFINE_STANDARD_ALLOC
Standard_Persistent() : _typenum(0), _refnum(0) {}
DEFINE_STANDARD_RTTIEXT(Standard_Persistent,Standard_Transient)
Standard_Integer& TypeNum() { return _typenum; }
private:
Standard_Integer _typenum;
Standard_Integer _refnum;
friend class Storage_Schema;
};
9.Standard_Type
class Standard_Type : public Standard_Transient {
public:
Standard_CString SystemName() const { return myInfo.name(); }
Standard_CString Name() const { return myName; }
Standard_Size Size() const { return mySize; }
const Handle(Standard_Type)& Parent () const { return myParent; }
Standard_EXPORT Standard_Boolean SubType (const Handle(Standard_Type)& theOther) const{
return ! theOther.IsNull()
&& (theOther == this || (! myParent.IsNull() && myParent->SubType (theOther)));
}
Standard_EXPORT Standard_Boolean SubType (const Standard_CString theOther) const{
return theName != 0
&& (IsEqual (myName, theName) || (! myParent.IsNull() && myParent->SubType (theName)));
}
Standard_EXPORT void Print (Standard_OStream& AStream) const{
AStream << std::hex << (Standard_Address)this << " : " << std::dec << myName ;
}
template <class T>
static const Handle(Standard_Type)& Instance() {
return opencascade::type_instance<T>::get();
}
Standard_EXPORT static Standard_Type* Register (const std::type_info& theInfo, const char* theName, Standard_Size theSize, const Handle(Standard_Type)& theParent){
static Standard_Mutex theMutex;
Standard_Mutex::Sentry aSentry (theMutex);
registry_type& aRegistry = GetRegistry();
Standard_Type* aType = 0;
auto anIter = aRegistry.find(theInfo);
if (anIter != aRegistry.end())
return anIter->second;
aType = new Standard_Type (theInfo, theName, theSize, theParent);
aRegistry.emplace(theInfo, aType);
return aType;
}
Standard_EXPORT ~Standard_Type (){
registry_type& aRegistry = GetRegistry();
Standard_ASSERT(aRegistry.erase(myInfo) > 0,
"Standard_Type::~Standard_Type() cannot find itself in registry",);
}
DEFINE_STANDARD_RTTIEXT(Standard_Type,Standard_Transient)
private:
Standard_Type (const std::type_info& theInfo, const char* theName, Standard_Size theSize, const Handle(Standard_Type)& theParent);
private:
std::type_index myInfo; //!< Object to store system name of the class
Standard_CString myName; //!< Given name of the class
Standard_Size mySize; //!< Size of the class instance, in bytes
Handle(Standard_Type) myParent; //!< Type descriptor of parent class
};
RTTI识别系统识别类型所需的信息。



















