999999999 内存泄漏问题
class CQueue
{
public:
struct ELEMENT
{
int m_nThreadNum,m_nRequestNum;
};
typedef ELEMENT* PELEMENT;
private:
PELEMENT m_pElements;
int m_nMaxElements;
HANDLE m_h[2];
HANDLE &m_hmtxQ;
HANDLE &m_hsenNumElements;
public:
CQueue(int nMaxElements);
~CQueue();
BOOL Append(ELEMENT &pElement, DWORD dwTimeout);
BOOL Remove(ELEMENT &pElement, DWORD dwTimeout);
};
CQueue::CQueue(int nMaxElements):m_hmtxQ(m_h[0]),m_hsenNumElements(m_h[1])
{
m_pElements = (PELEMENT)HeapAlloc(GetProcessHeap(),0,sizeof(ELEMENT)*nMaxElements);
m_nMaxElements = nMaxElements;
m_hmtxQ = CreateMutex(NULL,FALSE,NULL);
m_hsenNumElements = CreateSemaphore(NULL,0,nMaxElements,NULL);
}
CQueue::~CQueue()
{
CloseHandle(m_hsenNumElements);
CloseHandle(m_hmtxQ);
HeapFree(GetProcessHeap(),0,m_pElements);
}
BOOL CQueue::Append(ELEMENT &pElement, DWORD dwTimeout)
{
BOOL fOK = FALSE;
DWORD dw = WaitForSingleObject(m_hmtxQ,dwTimeout);
if(dw == WAIT_OBJECT_0)
{
LONG IPrevCount;
fOK = ReleaseSemaphore(m_hsenNumElements,1,&IPrevCount);
if(fOK)
{
m_pElements[IPrevCount].m_nThreadNum = pElement.m_nThreadNum;
m_pElements[IPrevCount].m_nRequestNum = pElement.m_nRequestNum;
}
else
{
SetLastError(ERROR_DATABASE_FULL);//溢出
}
ReleaseMutex(m_hmtxQ);
}
else
{
SetLastError(ERROR_TIMEOUT);
}
return(fOK);
}
BOOL CQueue::Remove(ELEMENT &pElement, DWORD dwTimeout)
{
BOOL fOK = ( WaitForMultipleObjects(2,m_h,TRUE,dwTimeout ) == WAIT_OBJECT_0 );
if(fOK)
{
pElement = m_pElements[0];
MoveMemory(&m_pElements[0],&m_pElements[1],sizeof(ELEMENT)*(m_nMaxElements-1));//移出一个
ReleaseMutex(m_hmtxQ);
}
else
{
SetLastError(ERROR_TIMEOUT);
}
return(fOK);
}
class CDlgqueue : public CDialog
{
// Construction
public:
CDlgqueue(CWnd* pParent = NULL); // standard constructor
HANDLE m_handle;
// Dialog Data
//{{AFX_DATA(CDlgqueue)
enum { IDD = IDD_DIALOG2 };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDlgqueue)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CDlgqueue)
virtual BOOL OnInitDialog();
afx_msg void OnButton2();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
static DWORD WINAPI ClientThread(LPVOID pvPara);
static DWORD WINAPI ServerThread(LPVOID pvPara);
static DWORD WINAPI ButtonThread(LPVOID pvPara);
};
#include "stdafx.h"
#include "msg.h"
#include "Dlgqueue.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
volatile BOOL g_fshutdown = TRUE;
HWND g_hwnd;
CQueue g_q(10);
HANDLE g_hThreads[MAXIMUM_WAIT_OBJECTS];
int g_nNumThreads;
/////////////////////////////////////////////////////////////////////////////
// CDlgqueue dialog
CDlgqueue::CDlgqueue(CWnd* pParent /*=NULL*/)
: CDialog(CDlgqueue::IDD, pParent)
{
//{{AFX_DATA_INIT(CDlgqueue)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
g_nNumThreads= 0;
}
void CDlgqueue::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDlgqueue)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDlgqueue, CDialog)
//{{AFX_MSG_MAP(CDlgqueue)
ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDlgqueue message handlers
BOOL CDlgqueue::OnInitDialog()
{
CDialog::OnInitDialog();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
DWORD WINAPI CDlgqueue::ClientThread(LPVOID pvPara)
{
int nThreadNum = PtrToUlong(pvPara);
HWND hwndLB = ::GetDlgItem(g_hwnd,IDC_LISTCLIENT);
for(int nRequestNum = 1; g_fshutdown; nRequestNum++)
{
try
{
TCHAR sz[1024];
CQueue::ELEMENT e = {nThreadNum,nRequestNum};
if(g_q.Append(e,200))
{
wsprintf(sz,TEXT("Sending %d:%d"),nThreadNum,nRequestNum);
}
else
{
wsprintf(sz,TEXT("Sending %d:%d(%s)"),nThreadNum,nRequestNum,
(GetLastError() == ERROR_TIMEOUT) ? TEXT("timeout"):TEXT("full") );
}
ListBox_SetCurSel(hwndLB,ListBox_AddString(hwndLB,sz) );
Sleep(2500);
}
catch (...)
{
Sleep(1000);
}
}
return(0);
}
DWORD WINAPI CDlgqueue::ServerThread(LPVOID pvPara)
{
int nThreadNum = PtrToUlong(pvPara);
HWND hwndLB = ::GetDlgItem(g_hwnd,IDC_LISTSERVER);
while (g_fshutdown)
{
try
{
TCHAR sz[1024];
CQueue::ELEMENT e;
if(g_q.Remove(e,5000))
{
wsprintf(sz,TEXT("%d:Processing %d:%d"),nThreadNum,e.m_nThreadNum,e.m_nRequestNum);
Sleep(2000*e.m_nThreadNum);
}
else
{
wsprintf(sz,TEXT("%d:(timeout)"),nThreadNum);
}
ListBox_SetCurSel(hwndLB,ListBox_AddString(hwndLB,sz) );
}
catch (...)
{
Sleep(1000);
}
}
return(0);
}
void CDlgqueue::OnButton2()
{
g_hwnd = this->m_hWnd;
InterlockedExchange((LONG*)&g_fshutdown,(LONG)TRUE);
for(int x=0;x<4;x++)
{
g_hThreads[g_nNumThreads++]=::CreateThread(NULL,0,ClientThread,(PVOID)(INT_PTR)x,0,NULL);
}
for(x=0;x<2;x++)
{
g_hThreads[g_nNumThreads++]=::CreateThread(NULL,0,ServerThread,(PVOID)(INT_PTR)x,0,NULL);
}
m_handle = ::CreateThread(NULL,0,ButtonThread,this,0,NULL);
/*
WaitForMultipleObjects(g_nNumThreads,g_hThreads,TRUE,INFINITE);
while (g_nNumThreads--)
{
CloseHandle(g_hThreads[g_nNumThreads]);
}*/
}
DWORD WINAPI CDlgqueue::ButtonThread(LPVOID pvPara)
{
WaitForMultipleObjects(g_nNumThreads,g_hThreads,TRUE,INFINITE);
while (g_nNumThreads--)
{
CloseHandle(g_hThreads[g_nNumThreads]);
}
return(0);
}