TKernel模塊--雜項

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_ALLOCDEFINE_NCOLLECTION_ALLOCNCollection_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 _WIN32myPageSize = getpagesize();if ( ! myPageSize )myMMap = 0;#elseSYSTEM_INFO SystemInfo;GetSystemInfo (&SystemInfo);myPageSize = SystemInfo.dwPageSize;#endifif(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 _WIN32const 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 debugnPool += 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; elsemyFreeList[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;elsemyAllocList = aNext;}FreeMemory(aPools[iPool], PoolSize);}aPrevPool = (aFreePools[iLastFree] == iLast ? aPrev : aPools[iLast]);(void )nPoolFreed; // unused but set for debugnPoolFreed += iLastFree + 1;}return nbFreed;}void FreeMemory (Standard_Address aPtr, const Standard_Size aSize){if ( myMMap ) {#ifndef _WIN32const Standard_Size AlignedSize = PAGE_ALIGN(aSize, myPageSize);munmap((char*)aBlock, AlignedSize);#elseconst HANDLE * aMBlock = (const HANDLE *)aBlock;HANDLE hMap = *(--aMBlock);UnmapViewOfFile((LPCVOID)aMBlock);CloseHandle (hMap);#endif}elsefree(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);// 內存部分需要清理}// 對應的小塊鏈表為孔,且對齊后尺寸不超過myCellSizeelse 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 _WIN32const 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);}// 一開始存儲hMapaMBlock[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_ALLOCStandard_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 classStandard_CString myName;        //!< Given name of the classStandard_Size mySize;           //!< Size of the class instance, in bytesHandle(Standard_Type) myParent; //!< Type descriptor of parent class
};

RTTI識別系統識別類型所需的信息。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/83135.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/83135.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/83135.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

c++ typeid運算符

typeid運算符能獲取類型信息。獲取到的是type_info對象。type_info類型如下&#xff1a; 可以看到&#xff0c;這個類刪除了拷貝構造函數以及等號操作符。有一些成員函數&#xff1a;hash_code、before、name、raw_name, 還重載了和!運算符。 測試&#xff1a; void testTyp…

第304個Vulnhub靶場演練攻略:digital world.local:FALL

digital world.local&#xff1a;FALL Vulnhub 演練 FALL (digitalworld.local: FALL) 是 Donavan 為 Vulnhub 打造的一款中型機器。這款實驗室非常適合經驗豐富的 CTF 玩家&#xff0c;他們希望在這類環境中檢驗自己的技能。那么&#xff0c;讓我們開始吧&#xff0c;看看如何…

【數據庫】數據庫恢復技術

數據庫恢復技術 實現恢復的核心是使用冗余&#xff0c;也就是根據冗余數據重建不正確數據。 事務 事務是一個數據庫操作序列&#xff0c;是一個不可分割的工作單位&#xff0c;是恢復和并發的基本單位。 在關系數據庫中&#xff0c;一個事務是一條或多條SQL語句&#xff0c…

switch-case判斷

switch-case判斷 #include <stdio.h> int main() {int type;printf("請輸入你的選擇&#xff1a;\n");scanf("%d",&type);getchar();switch (type){case 1:printf("你好&#xff01;");break;case 2:printf("早上好&#xff01;…

從監控到告警:Prometheus+Grafana+Alertmanager+告警通知服務全鏈路落地實踐

文章目錄 一、引言1.1 監控告警的必要性1.2 監控告警的基本原理1.2.1 指標采集與存儲1.2.2 告警規則與觸發機制1.2.3 多渠道通知與閉環 二、技術選型與架構設計2.1 為什么選擇 Prometheus 及其生態2.1.1 Prometheus 優勢分析2.1.2 Grafana 可視化能力2.1.3 Alertmanager 靈活告…

STM32 UART通信實戰指南:從原理到項目落地

STM32串口通信實戰指南&#xff1a;從零開始手把手教你 前言&#xff1a;為什么串口這么重要&#xff1f; 在嵌入式開發中&#xff0c;串口就像設備的"嘴巴"和"耳朵"。無論是給單片機下達指令、讀取傳感器數據&#xff0c;還是讓兩個模塊"對話"…

Jmeter requests

1.Jemter元件和組件 1.1 元件和組件的概念 元件&#xff1a;多個功能相似的的組件的容器&#xff0c;類似于一個工具箱。 組件&#xff1a;實現某個特定功能的實例&#xff0c;類似于工具箱中的螺絲刀&#xff0c;十字扳手... 1.2 作用域和執行順序 1.2.1 作用域 例子&#…

計算機視覺---GT(ground truth)

在計算機視覺&#xff08;Computer Vision, CV&#xff09;領域&#xff0c;Ground Truth&#xff08;GT&#xff0c;中文常譯為“真值”或“ ground truth”&#xff09; 是指關于數據的真實標簽或客觀事實&#xff0c;是模型訓練、評估和驗證的基準。它是連接算法與現實世界的…

1-Wire 一線式總線:從原理到實戰,玩轉 DS18B20 溫度采集

引言 在嵌入式系統中&#xff0c;通信總線是連接 CPU 與外設的橋梁。從 I2C、SPI 到 UART&#xff0c;每種總線都有其獨特的應用場景。而本文要介紹的1-Wire 一線式總線&#xff0c;以其極簡的硬件設計和獨特的通信協議&#xff0c;在溫度采集、身份識別等領域大放異彩。本文將…

基于開源AI大模型AI智能名片S2B2C商城小程序源碼的銷售環節數字化實現路徑研究

摘要&#xff1a;在數字化浪潮下&#xff0c;企業銷售環節的轉型升級已成為提升競爭力的核心命題。本文基于清華大學全球產業研究院《中國企業數字化轉型研究報告&#xff08;2020&#xff09;》提出的“提升銷售率與利潤率、打通客戶數據、強化營銷協同、構建全景用戶畫像、助…

Linux淺談

Linux淺談 一、什么是 Linux&#xff1f;先拋開 “內核”&#xff0c;看整體 可以把 Linux 系統 想象成一臺 “組裝電腦”&#xff1a; 最核心的零件是 “主板”—— 這就是 Linux 內核&#xff08;Kernel&#xff09;&#xff0c;負責管理電腦里的所有硬件&#xff08;比如 …

PostgreSQL ERROR: out of shared memory處理

使用pg_dump命令導出一個庫的時候&#xff0c;報 pg_dump: error: query failed: ERROR: out of shared memory HINT: You might need to increase "max_locks_per_transaction". 從錯誤字面上看是超出內存大小了&#xff0c;建議增加max_locks_per_transaction參…

IoT/基于NB28-A/BC28-CNV通信模組使用AT指令連接華為云IoTDA平臺(HCIP-IoT實驗2)

文章目錄 概述檢查通信環境通信模組固件信號強度CGATT指令參數 / 啥是PS域&#xff1f;PS附著狀態&#xff1a;ATCGATTPLMN 選擇&#xff1a;ATCOPSCEREG指令參數 / 啥是EPS與EPC?CEREG指令參數 / 啥是URC?網絡注冊狀態&#xff1a;ATCEREG網絡附著和網絡注冊 AT指令接入IoTD…

紅外遙控(外部中斷)

目錄 1.紅外遙控簡介 通信方式&#xff1a; 紅外LED波長&#xff1a; 通信協議標準&#xff1a; 2.硬件電路 發送部分1&#xff1a; 內部元件介紹&#xff1a; 工作原理&#xff1a; 為什么要以38KHZ亮滅&#xff1f; 電路圖&#xff1a; 發送部分2&#xff1a; 電…

【C#】一個簡單的http服務器項目開發過程詳解

這跟安裝NoteJs程序運行腳本文件搭建一個簡單Http服務器一樣&#xff0c;相比起來&#xff0c;它的優點是可以開發的應用是免安裝&#xff0c;跨平臺的&#xff0c;放在移動盤上便捷的&#xff0c;這里著重講http服務器實現的過程&#xff0c;以便自主實現特定的功能和服務。 …

WPF【11_4】WPF實戰-重構與美化(MVVM 架構)

11-9 【理論】MVVM 架構 在 WPF 項目中&#xff0c;我們主要采用的是一種類似 MVC 的架構&#xff0c;叫做 MVVM。 MVVM 繼承了 MVC 的理念&#xff0c;是 Model-View-ViewModel 的縮寫&#xff0c;中文意思是模型、視圖、視圖模型。這三個詞分開看我們都能看懂&#xff0c;不…

使用PowerBI個人網關定時刷新數據

使用PowerBI個人網關定時刷新數據 PowerBI desktop連接mysql&#xff0c;可以設置定時刷新數據或在PowerBI服務中手動刷新數據,步驟如下&#xff1a; 第一步&#xff1a; 下載網關。以個人網關為例&#xff0c;如圖 第二步&#xff1a; 雙擊網關&#xff0c;點擊下一步&…

深度學習驅動的超高清圖修復技術——綜述

Deep Learning-Driven Ultra-High-Definition Image Restoration: A Survey Liyan Wang, Weixiang Zhou, Cong Wang, Kin-Man Lam, Zhixun Su, Jinshan Pan Abstract Ultra-high-definition (UHD) image restoration?? aims to specifically solve the problem of ??quali…

3 分鐘學會使用 Puppeteer 將 HTML 轉 PDF

需求背景 1、網頁存檔與文檔管理 需要將網頁內容長期保存或歸檔為PDF,確保內容不被篡改或丟失,適用于法律文檔、合同、技術文檔等場景。PDF格式便于存儲和檢索。 2、電子報告生成 動態生成的HTML內容(如數據分析報告、儀表盤)需導出為PDF供下載或打印。PDF保留排版和樣…

電子郵箱設置SSL:構建郵件傳輸的加密護城河

在數字化通信高度依賴的今天&#xff0c;電子郵件作為企業協作與個人隱私的核心載體&#xff0c;其安全性直接關系到數據主權與商業利益。SSL&#xff08;Secure Sockets Layer&#xff09;作為網絡通信加密的基石技術&#xff0c;通過為郵件傳輸建立加密隧道&#xff0c;有效抵…