TKernel模块--杂项

news2025/12/17 11:09:50

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识别系统识别类型所需的信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2394303.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

充电便捷,新能源汽车移动充电服务如何预约充电

随着新能源汽车的普及&#xff0c;充电便捷性成为影响用户体验的关键因素之一。传统的固定充电桩受限于地理位置和数量&#xff0c;难以完全满足用户需求&#xff0c;而移动充电服务的出现&#xff0c;为车主提供了更加灵活的补能方式。通过手机APP、小程序或在线平台&#xff…

基于 Chrome 浏览器扩展的Chroma简易图形化界面

简介 ChromaDB Manager 是基于 Chrome 浏览器扩展的一款 ChromaDB&#xff08;一个流行的向量数据库&#xff09;的数据查询工具。提供了一个用户友好的界面&#xff0c;可以直接从浏览器连接到本地 ChromaDB 实例、查看集合信息和分片数据。本工具特别适合开发人员快速查看和…

IM系统的负载均衡

1.IM场景的负载均衡 2.方案总览 SDK层想要连接一个TCP网关或者WebSocket网关的方案 SDK单地址:在SDK中写死某个网关的IP或者域名,缺点是更换地址需要重新打包SDK SDK多地址:防止某一个地址嗝屁了写上多个地址用足保持高可用 暴露接口给客户端:SDK层访问接口动态获得地址 注…

使用 Zabbix 监控 MySQL 存储空间和性能指标的完整实践指南

目录 引言 一、最终目标支持功能 二、监控方案设计 2.1 技术选型 2.2 设计思路 三、实现步骤 3.1 准备工作 3.11 创建 MySQL 监控账号 3.12 配置 .my.cnf 文件 3.2 编写统一脚本 3.3 配置 Zabbix Agent UserParameter 3.4 Zabbix 前端配置建议 四、总结 引言 MySQL …

【技能拾遗】——家庭宽带单线复用布线与配置(移动2025版)

&#x1f4d6; 前言&#xff1a;在家庭网络拓扑中&#xff0c;客厅到弱电箱只预埋了一根网线&#xff0c;由于已将广电的有线电视取消并改用IPTV。现在需要解决在客厅布置路由器和观看IPTV问题&#xff0c;这里就用到单线复用技术。 目录 &#x1f552; 1. 拓扑规划&#x1f55…

异步日志监控:FastAPI与MongoDB的高效整合之道

title: 异步日志监控:FastAPI与MongoDB的高效整合之道 date: 2025/05/27 17:49:39 updated: 2025/05/27 17:49:39 author: cmdragon excerpt: FastAPI与MongoDB整合实现日志监控系统的实战指南。首先配置MongoDB异步连接,定义日志数据模型。核心功能包括日志写入接口、聚合…

在 Android 上备份短信:保护您的对话

尽管我们的Android手机有足够的存储空间来存储无数的短信&#xff0c;但由于设备故障、意外删除或其他意外原因&#xff0c;您可能会丢失重要的对话。幸运的是&#xff0c;我们找到了 5 种有效的 Android SMS 备份解决方案&#xff0c;确保您的数字聊天和信息保持安全且可访问。…

标题:2025海外短剧爆发年:APP+H5双端系统开发,解锁全球流量与变现新大陆

描述&#xff1a; 2025年出海新风口&#xff01;深度解析海外短剧系统开发核心&#xff08;APPH5双端&#xff09;&#xff0c;揭秘高效开发策略与商业化路径&#xff0c;助您抢占万亿美元市场&#xff01; 全球娱乐消费模式正在剧变。2025年&#xff0c;海外短剧市场已从蓝海…

解决RAGFlow(v0.19.0)有部分PDF无法解析成功的问题。

ragflow版本为&#xff1a;v0.19.0 1.解析的时候报错&#xff1a;Internal server error while chunking: Coordinate lower is less than upper。 看报错怀疑是分片的问题&#xff0c;于是把文档的切片方法中的“建议文本块大小”数值&#xff08;默认512&#xff09;调小&…

c#基础08(数组)

文章目录 数组数组概念声明数组初始化数组赋值给数组访问数组元素 集合动态数组(ArrayList)使用foreach循环C#数组细节多维数组传递数组给函数参数数组 数组 数组概念 数组是一个存储相同类型元素的固定大小的顺序集合。数组是用来存储数据的集合&#xff0c;通常认为数组是一…

嵌入式学习--江协stm32day3

这是我目前为止认为最重要的模块--TIM定时器&#xff0c;这里我们主要学习通用定时器 最小的计数计时单元为时基单元&#xff0c;包括PSC&#xff0c;ARR&#xff0c;CNT CK_PSC&#xff08;Prescaler&#xff0c;预分频器&#xff09;&#xff1a;作用是对输入时钟信号进行分…

4.8.1 利用Spark SQL实现词频统计

在利用Spark SQL实现词频统计的实战中&#xff0c;首先需要准备单词文件并上传至HDFS。接着&#xff0c;可以通过交互式方法或创建Spark项目来实现词频统计。交互式方法包括读取文本文件生成数据集&#xff0c;扁平化映射得到新数据集&#xff0c;然后将数据集转成数据帧&#…

PyTorch中nn.Module详解

直接print(dir(nn.Module))&#xff0c;得到如下内容&#xff1a; 一、模型结构与参数 parameters() 用途&#xff1a;返回模块的所有可训练参数&#xff08;如权重、偏置&#xff09;。示例&#xff1a;for param in model.parameters():print(param.shape)named_parameters…

动态表单开发避坑:改变input的值不会触发change事件即时修复策略-WdatePicker ——仙盟创梦IDE

原始传统模式 onchange <input onchange"未来之窗东方仙盟change(this)" oni > <script>function 未来之窗东方仙盟change(onj){console.log("未来之窗东方仙盟change",onj.value)} </script> 测试 原始传统模式 oninput <input …

10.安卓逆向2-frida hook技术-frida基本使用-frida指令(用于hook)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;图灵Python学院 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取码&#xff1…

动态设置微信小程序页面标题(navigationBarTitleText属性)

前言&#xff1a; 最近在公司进行小程序研发的时候&#xff0c;产品给出了一个动态加载页面标题的需求&#xff0c;经过调研之后将结果在这里与各位伙伴进行分享。 代码展示&#xff1a; 在.json文件中进行初始配置&#xff1a; { "usingComponents": {}, &q…

Flutter下的一点实践

目录 1、背景2、refena创世纪代码3、localsend里refena的刷新3.1 初始状态3.2 发起设备扫描流程3.3 扫描过程3.3 刷新界面 4.localsend的设备扫描流程4.1 UDP广播设备注册流程4.2 TCP/HTTP设备注册流程4.3 localsend的服务器初始化工作4.4总结 1、背景 在很久以前&#xff0c;…

VScode ios 模拟器安装cocoapods

使用 Homebrew 安装&#xff08;推荐&#xff09; 如果你有 Homebrew&#xff0c;直接用它安装更稳定&#xff1a; brew install cocoapods

Redis最佳实践——安全与稳定性保障之数据持久化详解

Redis 在电商应用的安全与稳定性保障之数据持久化全面详解 一、持久化机制深度解析 1. 持久化策略矩阵 策略触发方式数据完整性恢复速度适用场景RDB定时快照分钟级快容灾备份/快速恢复AOF实时追加日志秒级慢金融交易/订单关键操作混合模式RDBAOF同时启用秒级中等高安全要求场…

K 值选对,准确率翻倍:KNN 算法调参的黄金法则

目录 一、背景介绍 二、KNN 算法原理 2.1 核心思想 2.2 距离度量方法 2.3 算法流程 2.4算法结构&#xff1a; 三、KNN 算法代码实现 3.1 基于 Scikit-learn 的简单实现 3.2 手动实现 KNN&#xff08;自定义代码&#xff09; 四、K 值选择与可视化分析 4.1 K 值对分类…