ultimatepp/uppsrc/TCore/atexit.cpp
mdelfede 263ff5f895 changed svn layout
git-svn-id: svn://ultimatepp.org/upp/trunk@281 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2008-06-07 22:31:27 +00:00

82 lines
1.7 KiB
C++

#include "TCore.h"
#ifdef PLATFORM_WIN32
#if defined(COMPILER_MSC6) && !defined(flagSO)
typedef void (__cdecl *_PVFV)(void);
//typedef int (__cdecl * _onexit_t)(void);
extern "C" _PVFV *__onexitbegin;
extern "C" _PVFV *__onexitend;
enum { BLOCKSIZE = 1022 };
struct OnExitBlock
{
int count;
OnExitBlock *prev_block;
_PVFV pointers[BLOCKSIZE];
};
static OnExitBlock *onexitlist = NULL;
static bool lockexit = false;
inline static OnExitBlock *AtExitAlloc()
{
return (OnExitBlock *)GlobalAlloc(GMEM_FIXED, sizeof(OnExitBlock));
}
inline static void AtExitFree(OnExitBlock *block)
{
GlobalFree((HGLOBAL)block);
}
static void __cdecl AtExitDestroy()
{
// ASSERT(lockexit);
#ifdef _DEBUG
int total = 0;
for(OnExitBlock *p = onexitlist; p; p = p -> prev_block)
total += p -> count;
LOG("AtExitDestroy: " << total << " atexit functions");
#endif//_DEBUG
while(onexitlist)
{
while(onexitlist -> count > 0)
onexitlist -> pointers[--onexitlist -> count]();
OnExitBlock *prev = onexitlist -> prev_block;
AtExitFree(onexitlist);
onexitlist = prev;
}
}
void lockatexit()
{
lockexit = true;
}
extern "C" int __cdecl atexit(_PVFV func)
{
if(!func)
return 0; // silently ignore NULL pointers
ASSERT(!lockexit);
if(!onexitlist || onexitlist -> count >= BLOCKSIZE)
{
if(!onexitlist)
{
ASSERT(__onexitbegin == NULL);
static _PVFV exitlist[1] = { &AtExitDestroy };
__onexitend = (__onexitbegin = exitlist) + 1;
}
OnExitBlock *new_block = AtExitAlloc();
ASSERT(new_block);
new_block -> count = 0;
new_block -> prev_block = onexitlist;
onexitlist = new_block;
}
onexitlist -> pointers[onexitlist -> count++] = func;
return 0;
}
#endif
#endif