Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

237 lines
4.5 KiB

//***************************************************************************
//
// File:
//
// Module: MS SNMP Provider
//
// Purpose:
//
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
/*
* THREAD.CPP
*
* Implemenation of thread wrapper class.
*/
#include <precomp.h>
#include "csmir.h"
#include "smir.h"
#include "handles.h"
#include "classfac.h"
#include "thread.h"
#include <textdef.h>
#ifdef ICECAP_PROFILE
#include <icapexp.h>
#endif
ThreadMap <CThread*, CThread*, CThread*,CThread*> CThread :: m_ThreadMap ;
CThread :: CThread()
{
m_cRef=1;
bWaiting=FALSE;
m_ulThreadHandle = NULL;
m_hThreadStopEvent= NULL;
if(NULL == (m_hThreadStopEvent = CreateEvent(NULL, FALSE,
FALSE, NULL)))
{
// WBEM_E_FAILED;
}
if(NULL == (m_hThreadSyncEvent = CreateEvent(NULL, FALSE,
FALSE, NULL)))
{
// WBEM_E_FAILED;
}
m_ThreadMap.SetAt(this,this);
}
CThread::operator void*()
{
if((NULL != m_hThreadStopEvent) && (NULL != m_hThreadStopEvent))
{
//the thread has been created
return this;
}
else
{
//the thread is invalid
return (void*)NULL;
}
}
ULONG CThread :: Release()
{
if (0!=--m_cRef)
{
return m_cRef;
}
delete this;
return 0;
}
CThread:: ~CThread()
{
//clean-up
if(m_hThreadStopEvent)
{
CloseHandle(m_hThreadStopEvent);
}
if(m_hThreadSyncEvent)
{
CloseHandle(m_hThreadSyncEvent);
}
m_ThreadMap.RemoveKey(this);
}
void __cdecl GenericThreadProc(void *arglist)
{
SetStructuredExceptionHandler seh;
try
{
HRESULT hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
try
{
CThread *pThreadObject = (CThread*) arglist;
if(S_OK == hr)
{
hr = pThreadObject->Process();
if(SMIR_THREAD_DELETED != hr)
{
pThreadObject->Exit();
}
//else the thread has just been deleted
}
}
catch(...)
{
CoUninitialize();
throw;
}
CoUninitialize();
}
}
catch(Structured_Exception e_SE)
{
return;
}
catch(Heap_Exception e_HE)
{
return;
}
catch(...)
{
return;
}
}
#pragma warning (disable:4018)
SCODE CThread :: Wait(DWORD timeout)
{
//create an array of wait events
int iNumberOfEvents = m_UserEvents.GetCount()+1;
HANDLE *lpHandles = new HANDLE[iNumberOfEvents];
POSITION rNextPosition;
UINT iLoop=0;
for(rNextPosition=m_UserEvents.GetStartPosition();
(NULL!=rNextPosition)&&(iLoop<iNumberOfEvents);iLoop++)
{
HANDLE lKey = 0;
HANDLE pItem = NULL;
m_UserEvents.GetNextAssoc(rNextPosition, lKey, pItem );
lpHandles[iLoop] = pItem;
}
lpHandles[iNumberOfEvents-1] = m_hThreadStopEvent;
//signal to the exit code that we are waiting
bWaiting =TRUE;
//wait for an event to fire
DWORD dwResult = WaitForMultipleObjects(iNumberOfEvents,
lpHandles, FALSE, timeout);
bWaiting =FALSE;
delete [] lpHandles;
if(dwResult == iNumberOfEvents-1)
{
//thread stopped
return WAIT_EVENT_TERMINATED;
}
else if (( ( dwResult<(iNumberOfEvents-1) ) ) ||
(dwResult == WAIT_TIMEOUT) )
{
//a user event fired
return dwResult;
}
else if ((WAIT_ABANDONED_0 >= dwResult)&&(dwResult<(WAIT_ABANDONED_0+iNumberOfEvents)))
{
//it gave up
return (WAIT_EVENT_ABANDONED+(dwResult-WAIT_ABANDONED_0)-1);
}
//else the wait call failed
return WAIT_EVENT_FAILED;
}
#pragma warning (default:4018)
SCODE CThread :: Start()
{
//kick of the thread
if(NULL == (void*)*this)
{
//creation failed
return WBEM_E_FAILED;
}
if(NULL != m_ulThreadHandle)
{
//already running
return THREAD_STARED;
}
if(-1==(m_ulThreadHandle = _beginthread (&GenericThreadProc, 0,((void*) this))))
{
//begin thread failed
return WBEM_E_FAILED;
}
return S_OK;
}
SCODE CThread :: Stop ()
{
if(NULL==(void*)(*this)||(-1 == m_ulThreadHandle))
{
return WBEM_E_FAILED;
}
//terminate the thread if someone is waiting for it
if(bWaiting)
{
SetEvent(m_hThreadStopEvent);
WaitForSingleObject(m_hThreadSyncEvent,INFINITE);
}
//else just exit
return S_OK;
}
void CThread :: ProcessDetach()
{
POSITION rNextPosition;
UINT iLoop=0;
for(rNextPosition=m_ThreadMap.GetStartPosition();
NULL!=rNextPosition;iLoop++)
{
CThread *plKey = 0;
CThread *pItem = NULL;
m_ThreadMap.GetNextAssoc(rNextPosition, plKey, pItem );
pItem->Release () ;
}
}