// main.cpp
#include "ThreadPrivateHeapAllocated.h"
#include <process.h>
#include <iostream>
using namespace std;
static const int NUM_ALLOCS = 20000;
static const int NUM_THREADS = 4;
class ClassAllocatedFromProcessHeap {
public:
protected:
char m_buffer[1024];
};
class ClassAllocatedFromPrivateHeap :
public CThreadPrivateHeapAllocated {
public:
protected:
char m_buffer[1024];
};
class CThread {
public:
CThread()
{
m_hThread =
(HANDLE) _beginthreadex(
NULL, // no security attributes
0, // default stack size
threadFunc, // starting address
(LPVOID) this, // argument to threadFunc
CREATE_SUSPENDED, // create suspended
(UINT*)&m_dwThreadID ); // [out] thread ID
}
virtual ~CThread()
{ CloseHandle( m_hThread ); }
DWORD Start()
{ return ResumeThread( m_hThread ); }
virtual DWORD ThreadMain()=0;
HANDLE GetThreadHandle()
{ return m_hThread; }
protected:
static UINT _stdcall threadFunc( LPVOID lpControlledThread )
{
CThread* pThread =
reinterpret_cast<CThread*>(lpControlledThread);
return pThread->ThreadMain();
}
HANDLE m_hThread;
DWORD m_dwThreadID;
};
class CThreadUsingProcessHeap : public CThread {
public:
virtual DWORD ThreadMain()
{
for( int i=0; i<NUM_ALLOCS; i++ ) {
ClassAllocatedFromProcessHeap* p =
new ClassAllocatedFromProcessHeap;
delete p;
} // for
return 0;
}
};
class CThreadUsingPrivateHeap : public CThread {
public:
CThreadUsingPrivateHeap()
{ m_hHeap = HeapCreate( HEAP_NO_SERIALIZE, 0x100000, 0 ); }
virtual ~CThreadUsingPrivateHeap()
{ HeapDestroy( m_hHeap ); }
virtual DWORD ThreadMain()
{
TlsSetValue( CThreadPrivateHeapAllocated::GetTlsIndex(),
(LPVOID) m_hHeap );
for( int i=0; i<NUM_ALLOCS; i++ ) {
ClassAllocatedFromPrivateHeap* p =
new ClassAllocatedFromPrivateHeap;
delete p;
} // for
return 0;
}
protected:
HANDLE m_hHeap;
};
int main(int argc, char* argv[])
{
// Allocate a slot for thread-private heap handle. Let the
// CThreadPrivateHeapAllocated class know which slot number
// will be used...
CThreadPrivateHeapAllocated::SetTlsIndex( TlsAlloc() );
DWORD dwStart=0, dwEnd=0;
int i=0;
// ---------------------------------------------------------
// Do the test with single process heap...
CThreadUsingProcessHeap threadUsingProcessHeap[ NUM_THREADS ];
HANDLE hThreadUsingProcessHeap[NUM_THREADS];
dwStart = GetTickCount();
for( i=0; i<NUM_THREADS; i++ ) {
hThreadUsingProcessHeap[i] =
threadUsingProcessHeap[i].GetThreadHandle();
threadUsingProcessHeap[i].Start();
} // for
WaitForMultipleObjects( NUM_THREADS, hThreadUsingProcessHeap,
TRUE, INFINITE );
dwEnd = GetTickCount();
cout << "Test using single process heap took "
<< dwEnd-dwStart << " ms." << endl;
// ---------------------------------------------------------
// Do the test with private heap per thread...
CThreadUsingPrivateHeap threadUsingPrivateHeap[ NUM_THREADS ];
HANDLE hThreadUsingPrivateHeap[NUM_THREADS];
dwStart = GetTickCount();
for( i=0; i<NUM_THREADS; i++ ) {
hThreadUsingPrivateHeap[i] =
threadUsingPrivateHeap[i].GetThreadHandle();
threadUsingPrivateHeap[i].Start();
} // for
WaitForMultipleObjects( NUM_THREADS, hThreadUsingPrivateHeap,
TRUE, INFINITE );
dwEnd = GetTickCount();
cout << "Test using private heap per thread took "
<< dwEnd-dwStart << " ms." << endl;
TlsFree( CThreadPrivateHeapAllocated::GetTlsIndex() );
return 0;
}