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.
1417 lines
37 KiB
1417 lines
37 KiB
//***************************************************************************
|
|
//
|
|
// File:
|
|
//
|
|
// Module: MS SNMP Provider
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Copyright (c) 1997-2003 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "precomp.h"
|
|
#include <provexpt.h>
|
|
#include <snmptempl.h>
|
|
#include <snmpmt.h>
|
|
#include <typeinfo.h>
|
|
#include <process.h>
|
|
#include <objbase.h>
|
|
#include <stdio.h>
|
|
#include <snmpcont.h>
|
|
#include "snmpevt.h"
|
|
#include "snmpthrd.h"
|
|
#include "snmplog.h"
|
|
|
|
|
|
CCriticalSection SnmpThreadObject :: s_Lock ;
|
|
|
|
LONG SnmpThreadObject :: s_ReferenceCount = 0 ;
|
|
|
|
SnmpMap <DWORD,DWORD,SnmpThreadObject *,SnmpThreadObject *> SnmpThreadObject :: s_ThreadContainer ;
|
|
|
|
typedef ProvOnDelete < CRITICAL_SECTION *, VOID ( * ) ( LPCRITICAL_SECTION ), LeaveCriticalSection > LeaveCriticalSectionScope;
|
|
typedef ProvOnDelete < CRITICAL_SECTION *, VOID ( * ) ( LPCRITICAL_SECTION ), DeleteCriticalSection > DeleteCriticalSectionScope;
|
|
typedef WaitException < CRITICAL_SECTION *, VOID ( * ) ( LPCRITICAL_SECTION ), EnterCriticalSection, 1000 > EnterCriticalSectionWait;
|
|
|
|
class SnmpShutdownTaskObject : public SnmpTaskObject
|
|
{
|
|
private:
|
|
|
|
SnmpThreadObject* m_ThreadToShutdown ;
|
|
|
|
protected:
|
|
public:
|
|
|
|
SnmpShutdownTaskObject (SnmpThreadObject* threadToShutdown) ;
|
|
|
|
void Process () ;
|
|
|
|
} ;
|
|
|
|
SnmpShutdownTaskObject :: SnmpShutdownTaskObject (SnmpThreadObject* threadToShutdown)
|
|
: m_ThreadToShutdown ( threadToShutdown )
|
|
{
|
|
}
|
|
|
|
void SnmpShutdownTaskObject ::Process()
|
|
{
|
|
if (m_ThreadToShutdown)
|
|
{
|
|
m_ThreadToShutdown->SignalThreadShutdown();
|
|
}
|
|
|
|
Complete();
|
|
}
|
|
|
|
|
|
BOOL SnmpThreadObject :: Startup ()
|
|
{
|
|
InterlockedIncrement ( & s_ReferenceCount ) ;
|
|
|
|
return TRUE ;
|
|
}
|
|
|
|
void SnmpThreadObject :: Closedown()
|
|
{
|
|
#if DBG == 1
|
|
|
|
if ( s_ReferenceCount == 0 )
|
|
{
|
|
DebugBreak ();
|
|
}
|
|
|
|
#endif
|
|
|
|
if ( InterlockedDecrement ( & s_ReferenceCount ) <= 0 )
|
|
ProcessDetach () ;
|
|
}
|
|
|
|
void SnmpThreadObject :: ProcessAttach ()
|
|
{
|
|
}
|
|
|
|
void SnmpThreadObject :: ProcessDetach ( BOOL a_ProcessDetaching )
|
|
{
|
|
// delete all known thread objects
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
|
|
POSITION t_Position = s_ThreadContainer.GetStartPosition () ;
|
|
while ( t_Position )
|
|
{
|
|
DWORD t_EventId ;
|
|
SnmpThreadObject *t_ThreadObject ;
|
|
s_ThreadContainer.GetNextAssoc ( t_Position , t_EventId , t_ThreadObject ) ;
|
|
|
|
s_Lock.Unlock () ;
|
|
|
|
t_ThreadObject->SignalThreadShutdown () ;
|
|
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
|
|
t_Position = s_ThreadContainer.GetStartPosition () ;
|
|
}
|
|
|
|
s_ThreadContainer.RemoveAll () ;
|
|
s_Lock.Unlock () ;
|
|
}
|
|
|
|
void __cdecl SnmpThreadObject :: ThreadExecutionProcedure ( void *a_ThreadParameter )
|
|
{
|
|
SetStructuredExceptionHandler seh;
|
|
|
|
try
|
|
{
|
|
SnmpThreadObject *t_ThreadObject = ( SnmpThreadObject * ) a_ThreadParameter ;
|
|
BOOL bInitialised = FALSE;
|
|
|
|
try
|
|
{
|
|
t_ThreadObject->RegisterThread () ;
|
|
t_ThreadObject->Initialise () ;
|
|
bInitialised = TRUE;
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n [%S] Thread beginning dispatch" , t_ThreadObject->m_ThreadName ) ;
|
|
)
|
|
|
|
if ( t_ThreadObject->Wait () )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
}
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n [%S] Thread completed dispatch" , t_ThreadObject->m_ThreadName ) ;
|
|
)
|
|
|
|
t_ThreadObject->Uninitialise () ;
|
|
bInitialised = FALSE;
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Thread terminating" ) ;
|
|
)
|
|
}
|
|
catch(Structured_Exception e_SE)
|
|
{
|
|
t_ThreadObject->RemoveThread () ;
|
|
|
|
if ( bInitialised )
|
|
{
|
|
DebugMacro(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->Write ( L"\n *** [%S] Thread terminating -> structured exception *** " , t_ThreadObject->m_ThreadName ) ;
|
|
)
|
|
|
|
t_ThreadObject->Uninitialise () ;
|
|
}
|
|
|
|
return;
|
|
}
|
|
catch(Heap_Exception e_HE)
|
|
{
|
|
t_ThreadObject->RemoveThread () ;
|
|
|
|
if ( bInitialised )
|
|
{
|
|
DebugMacro(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->Write ( L"\n *** [%S] Thread terminating -> heap exception *** " , t_ThreadObject->m_ThreadName ) ;
|
|
)
|
|
|
|
t_ThreadObject->Uninitialise () ;
|
|
}
|
|
|
|
return;
|
|
}
|
|
catch(...)
|
|
{
|
|
t_ThreadObject->RemoveThread () ;
|
|
|
|
if ( bInitialised )
|
|
{
|
|
DebugMacro(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->Write ( L"\n *** [%S] Thread terminating -> exception *** " , t_ThreadObject->m_ThreadName ) ;
|
|
)
|
|
|
|
t_ThreadObject->Uninitialise () ;
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
DebugMacro(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->Write ( L"\n *** Thread terminating -> second chance exception *** " ) ;
|
|
)
|
|
}
|
|
}
|
|
|
|
void SnmpThreadObject :: TerminateThread ()
|
|
{
|
|
:: TerminateThread (m_ThreadHandle,0) ;
|
|
}
|
|
|
|
SnmpThreadObject :: SnmpThreadObject (
|
|
|
|
const char *a_ThreadName,
|
|
DWORD a_timeout
|
|
|
|
) : m_EventContainer ( NULL ) ,
|
|
m_EventContainerLength ( 0 ) ,
|
|
m_ThreadId ( 0 ) ,
|
|
m_ThreadHandle ( 0 ) ,
|
|
m_ThreadName ( NULL ) ,
|
|
m_timeout ( a_timeout ),
|
|
m_pShutdownTask ( NULL )
|
|
{
|
|
if ( a_ThreadName )
|
|
{
|
|
m_ThreadName = _strdup ( a_ThreadName ) ;
|
|
if( NULL == m_ThreadName) throw Heap_Exception(Heap_Exception::E_ALLOCATION_ERROR);
|
|
}
|
|
|
|
ConstructEventContainer () ;
|
|
|
|
}
|
|
|
|
void SnmpThreadObject :: BeginThread()
|
|
{
|
|
UINT_PTR t_PseudoHandle = _beginthread (
|
|
|
|
SnmpThreadObject :: ThreadExecutionProcedure ,
|
|
0 ,
|
|
( void * ) this
|
|
) ;
|
|
|
|
s_Lock.Lock () ;
|
|
LeaveCriticalSectionScope lcs ( s_Lock );
|
|
|
|
if ( ( HANDLE ) t_PseudoHandle != INVALID_HANDLE_VALUE )
|
|
{
|
|
BOOL t_Status = DuplicateHandle (
|
|
|
|
GetCurrentProcess () ,
|
|
( HANDLE ) t_PseudoHandle ,
|
|
GetCurrentProcess () ,
|
|
GetThreadHandleReference () ,
|
|
0 ,
|
|
TRUE ,
|
|
DUPLICATE_SAME_ACCESS
|
|
) ;
|
|
|
|
if ( ! t_Status )
|
|
{
|
|
throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL SnmpThreadObject :: WaitForStartup ()
|
|
{
|
|
BOOL bResult = FALSE;
|
|
|
|
SnmpTaskObject t_TaskObject ;
|
|
ScheduleTask ( t_TaskObject ) ;
|
|
t_TaskObject.Exec () ;
|
|
if ( ( bResult = t_TaskObject.Wait () ) == TRUE )
|
|
{
|
|
bResult = ReapTask ( t_TaskObject ) ;
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
SnmpThreadObject :: ~SnmpThreadObject ()
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Enter Thread destructor" ) ;
|
|
)
|
|
if ( ( m_ThreadId != GetCurrentThreadId () ) && ( m_ThreadId != 0 ))
|
|
{
|
|
SignalThreadShutdown () ;
|
|
}
|
|
|
|
free ( m_ThreadName ) ;
|
|
|
|
POSITION t_Position = m_TaskContainer.GetHeadPosition () ;
|
|
while ( t_Position )
|
|
{
|
|
SnmpAbstractTaskObject *t_TaskObject = m_TaskContainer.GetNext ( t_Position ) ;
|
|
|
|
t_TaskObject->DetachTaskFromThread ( *this ) ;
|
|
}
|
|
|
|
m_TaskContainer.RemoveAll () ;
|
|
|
|
free ( m_EventContainer ) ;
|
|
|
|
// we should have task already deleted by SignalThreadShutdown
|
|
EnterCriticalSectionWait ecs ( s_Lock );
|
|
s_ThreadContainer.RemoveKey ( m_ThreadId ) ;
|
|
s_Lock.Unlock () ;
|
|
|
|
if (m_pShutdownTask != NULL)
|
|
{
|
|
delete m_pShutdownTask;
|
|
}
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Exit Thread destructor" ) ;
|
|
)
|
|
|
|
}
|
|
|
|
void SnmpThreadObject :: PostSignalThreadShutdown ()
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Posting thread shutdown" ) ;
|
|
)
|
|
|
|
if (m_pShutdownTask != NULL)
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Thread shutdown previously posted" ) ;
|
|
)
|
|
}
|
|
else
|
|
{
|
|
m_pShutdownTask = new SnmpShutdownTaskObject(this);
|
|
ScheduleTask(*m_pShutdownTask);
|
|
m_pShutdownTask->Exec();
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Thread shutdown posted" ) ;
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
void SnmpThreadObject :: SignalThreadShutdown ()
|
|
{
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
LeaveCriticalSectionScope lcs ( s_Lock) ;
|
|
BOOL t_bRemoved = s_ThreadContainer.RemoveKey ( m_ThreadId ) ;
|
|
lcs.Exec ();
|
|
|
|
if (t_bRemoved)
|
|
{
|
|
// this should be safe now
|
|
if ( m_ThreadId == GetCurrentThreadId () )
|
|
{
|
|
m_ThreadTerminateEvent.Set () ;
|
|
}
|
|
else
|
|
{
|
|
HANDLE t_Handle = m_ThreadHandle ;
|
|
m_ThreadTerminateEvent.Set () ;
|
|
|
|
DWORD t_Event = WaitForSingleObject (
|
|
|
|
t_Handle ,
|
|
INFINITE
|
|
) ;
|
|
|
|
if ( t_Event != WAIT_OBJECT_0 )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
dwError = ::GetLastError ();
|
|
|
|
if ( dwError != ERROR_NOT_ENOUGH_MEMORY )
|
|
{
|
|
#if DBG == 1
|
|
// for testing purpose I will let process break
|
|
::DebugBreak();
|
|
#endif
|
|
}
|
|
|
|
while ( ERROR_SUCCESS != dwError )
|
|
{
|
|
// resources will eventually come back
|
|
::Sleep ( 1000 );
|
|
|
|
if ( WAIT_OBJECT_0 == WaitForSingleObject (
|
|
t_Handle ,
|
|
INFINITE
|
|
) )
|
|
{
|
|
// terminate loop
|
|
dwError = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseHandle ( t_Handle ) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SnmpThreadObject :: ConstructEventContainer ()
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Constructing Container" , m_ThreadName ) ;
|
|
)
|
|
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
LeaveCriticalSectionScope lcs ( s_Lock ) ;
|
|
|
|
BOOL bAllocated = FALSE;
|
|
do
|
|
{
|
|
ULONG origEventContainerLength = m_EventContainerLength ;
|
|
|
|
if ( ( m_TaskContainer.GetCount () + 2 ) < MAXIMUM_WAIT_OBJECTS )
|
|
{
|
|
m_EventContainerLength = m_TaskContainer.GetCount () + 2;
|
|
}
|
|
else
|
|
{
|
|
m_EventContainerLength = MAXIMUM_WAIT_OBJECTS - 1;
|
|
}
|
|
|
|
PVOID pNewMem = realloc ( m_EventContainer , sizeof ( HANDLE ) * m_EventContainerLength );
|
|
if ( pNewMem == NULL )
|
|
{
|
|
//
|
|
// revert the size back
|
|
//
|
|
m_EventContainerLength = origEventContainerLength ;
|
|
|
|
s_Lock.Unlock () ;
|
|
// system will eventually come back !
|
|
Sleep (60000);
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
}
|
|
else
|
|
{
|
|
m_EventContainer = ( HANDLE * ) pNewMem;
|
|
bAllocated = TRUE;
|
|
}
|
|
}
|
|
while ( ! bAllocated );
|
|
|
|
m_EventContainer [ 0 ] = GetHandle () ;
|
|
m_EventContainer [ 1 ] = m_ThreadTerminateEvent.GetHandle () ;
|
|
|
|
ULONG t_EventIndex = 2 ;
|
|
POSITION t_Position = m_TaskContainer.GetHeadPosition () ;
|
|
while ( t_Position && (t_EventIndex < m_EventContainerLength))
|
|
{
|
|
SnmpAbstractTaskObject *t_TaskObject = m_TaskContainer.GetNext ( t_Position ) ;
|
|
m_EventContainer [ t_EventIndex ] = t_TaskObject->GetHandle () ;
|
|
t_EventIndex ++ ;
|
|
}
|
|
}
|
|
|
|
void SnmpThreadObject :: RotateTask ( SnmpAbstractTaskObject *a_TaskObject )
|
|
{
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
LeaveCriticalSectionScope lcs ( s_Lock );
|
|
|
|
POSITION t_Position = m_TaskContainer.GetHeadPosition () ;
|
|
while ( t_Position )
|
|
{
|
|
POSITION t_LastPosition = t_Position ;
|
|
SnmpAbstractTaskObject *t_TaskObject = m_TaskContainer.GetNext ( t_Position ) ;
|
|
if ( a_TaskObject->GetHandle () == t_TaskObject->GetHandle () )
|
|
{
|
|
m_TaskContainer.RemoveAt ( t_LastPosition ) ;
|
|
m_TaskContainer.Add ( t_TaskObject ) ;
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
|
|
SnmpThreadObject *SnmpThreadObject :: GetThreadObject ()
|
|
{
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
LeaveCriticalSectionScope lcs ( s_Lock );
|
|
|
|
DWORD t_CurrentThreadId = GetCurrentThreadId () ;
|
|
|
|
SnmpThreadObject *t_ThreadObject ;
|
|
if ( s_ThreadContainer.Lookup ( GetCurrentThreadId () , t_ThreadObject ) )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
t_ThreadObject = NULL ;
|
|
}
|
|
|
|
return t_ThreadObject ;
|
|
}
|
|
|
|
SnmpAbstractTaskObject *SnmpThreadObject :: GetTaskObject ( HANDLE &a_Handle )
|
|
{
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
LeaveCriticalSectionScope lcs ( s_Lock );
|
|
|
|
POSITION t_Position = m_TaskContainer.GetHeadPosition () ;
|
|
while ( t_Position )
|
|
{
|
|
SnmpAbstractTaskObject *t_TaskObject = m_TaskContainer.GetNext ( t_Position ) ;
|
|
if ( t_TaskObject->GetHandle () == a_Handle )
|
|
{
|
|
return t_TaskObject ;
|
|
}
|
|
}
|
|
|
|
return NULL ;
|
|
}
|
|
|
|
BOOL SnmpThreadObject :: RegisterThread ()
|
|
{
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
LeaveCriticalSectionScope lcs ( s_Lock );
|
|
|
|
m_ThreadId = GetCurrentThreadId () ;
|
|
s_ThreadContainer [ m_ThreadId ] = this ;
|
|
|
|
BOOL t_Status = TRUE;
|
|
|
|
DebugMacro8(
|
|
|
|
wchar_t buffer [ 1025 ] ;
|
|
wsprintf ( buffer , L"\nThread [%S] = %lx, with thread id = %lx" , m_ThreadName , this , m_ThreadId ) ;
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, buffer ) ;
|
|
)
|
|
return t_Status ;
|
|
}
|
|
|
|
BOOL SnmpThreadObject :: RemoveThread ()
|
|
{
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
LeaveCriticalSectionScope lcs ( s_Lock );
|
|
|
|
BOOL t_Status = s_ThreadContainer.RemoveKey ( m_ThreadId ) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
DebugMacro8(
|
|
|
|
wchar_t buffer [ 1025 ] ;
|
|
wsprintf ( buffer , L"\nThread [%S] = %lx, with thread id = %lx was removed from container" , m_ThreadName , (UINT_PTR)this , m_ThreadId ) ;
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, buffer ) ;
|
|
)
|
|
}
|
|
else
|
|
{
|
|
DebugMacro8(
|
|
|
|
wchar_t buffer [ 1025 ] ;
|
|
wsprintf ( buffer , L"\nThread [%S] = %lx, with thread id = %lx failed to remove from container" , m_ThreadName , (UINT_PTR)this , m_ThreadId ) ;
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, buffer ) ;
|
|
)
|
|
}
|
|
|
|
return t_Status ;
|
|
}
|
|
|
|
void SnmpThreadObject :: Process ()
|
|
{
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
LeaveCriticalSectionScope lcs ( s_Lock );
|
|
|
|
POSITION t_Position = m_ScheduleReapEventContainer.GetStartPosition () ;
|
|
while ( t_Position )
|
|
{
|
|
HANDLE t_EventId ;
|
|
SnmpEventObject *t_Event ;
|
|
m_ScheduleReapEventContainer.GetNextAssoc ( t_Position , t_EventId , t_Event) ;
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Thread Process [%lx]" , m_ThreadName , t_EventId);
|
|
)
|
|
|
|
t_Event->Set () ;
|
|
}
|
|
}
|
|
|
|
BOOL SnmpThreadObject :: WaitDispatch ( ULONG t_HandleIndex , BOOL &a_Terminated )
|
|
{
|
|
BOOL t_Status = TRUE ;
|
|
|
|
HANDLE t_Handle = m_EventContainer [ t_HandleIndex ] ;
|
|
if ( t_Handle == GetHandle () )
|
|
{
|
|
// Task has been scheduled so we must update arrays
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Thread Wait: Refreshing handles" , m_ThreadName );
|
|
)
|
|
|
|
Process () ;
|
|
ConstructEventContainer () ;
|
|
}
|
|
else if ( t_Handle == m_ThreadTerminateEvent.GetHandle () )
|
|
{
|
|
// thread has been told to close down
|
|
|
|
a_Terminated = TRUE ;
|
|
m_ThreadTerminateEvent.Process () ;
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Someone t_Terminated" , m_ThreadName ) ;
|
|
)
|
|
}
|
|
else
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Thread Wait: Processing Task" , m_ThreadName );
|
|
)
|
|
|
|
SnmpAbstractTaskObject *t_TaskObject = GetTaskObject ( t_Handle ) ;
|
|
if ( t_TaskObject )
|
|
{
|
|
RotateTask ( t_TaskObject ) ;
|
|
ConstructEventContainer () ;
|
|
t_TaskObject->Process () ;
|
|
}
|
|
else
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Couldn't Find Task Object" , m_ThreadName ) ;
|
|
)
|
|
t_Status = FALSE ;
|
|
}
|
|
}
|
|
|
|
return t_Status ;
|
|
}
|
|
|
|
BOOL SnmpThreadObject :: Wait ()
|
|
{
|
|
BOOL t_Status = TRUE ;
|
|
BOOL t_Terminated = FALSE ;
|
|
|
|
while ( t_Status && ! t_Terminated )
|
|
{
|
|
DWORD t_Event = MsgWaitForMultipleObjects (
|
|
|
|
m_EventContainerLength ,
|
|
m_EventContainer ,
|
|
FALSE ,
|
|
m_timeout ,
|
|
QS_ALLINPUT
|
|
) ;
|
|
|
|
ULONG t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
|
|
|
|
if ( t_Event == 0xFFFFFFFF )
|
|
{
|
|
DWORD t_Error = GetLastError () ;
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Handle problem" , m_ThreadName ) ;
|
|
)
|
|
|
|
t_Status = FALSE ;
|
|
}
|
|
else if ( t_Event == WAIT_TIMEOUT)
|
|
{
|
|
TimedOut();
|
|
}
|
|
else if ( t_HandleIndex <= m_EventContainerLength )
|
|
{
|
|
// Go into dispatch loop
|
|
|
|
if ( t_HandleIndex == m_EventContainerLength )
|
|
{
|
|
BOOL t_DispatchStatus ;
|
|
MSG t_Msg ;
|
|
|
|
while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
|
|
{
|
|
int t_Result = 0;
|
|
t_Result = GetMessage ( & t_Msg , NULL , 0 , 0 );
|
|
|
|
if ( t_Result != 0 && t_Result != -1 )
|
|
{
|
|
TranslateMessage ( & t_Msg ) ;
|
|
DispatchMessage ( & t_Msg ) ;
|
|
}
|
|
|
|
BOOL t_Timeout = FALSE ;
|
|
|
|
while ( ! t_Timeout && t_Status && ! t_Terminated )
|
|
{
|
|
t_Event = WaitForMultipleObjects (
|
|
|
|
m_EventContainerLength ,
|
|
m_EventContainer ,
|
|
FALSE ,
|
|
0
|
|
) ;
|
|
|
|
t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
|
|
|
|
if ( t_Event == 0xFFFFFFFF )
|
|
{
|
|
DWORD t_Error = GetLastError () ;
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Handle problem" , m_ThreadName ) ;
|
|
)
|
|
t_Status = FALSE ;
|
|
}
|
|
else if ( t_Event == WAIT_TIMEOUT)
|
|
{
|
|
t_Timeout = TRUE ;
|
|
}
|
|
else if ( t_HandleIndex < m_EventContainerLength )
|
|
{
|
|
t_Status = WaitDispatch ( t_HandleIndex , t_Terminated ) ;
|
|
}
|
|
else
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Unknown handle index" , m_ThreadName ) ;
|
|
)
|
|
t_Status = FALSE ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( t_HandleIndex < m_EventContainerLength )
|
|
{
|
|
t_Status = WaitDispatch ( t_HandleIndex , t_Terminated ) ;
|
|
}
|
|
else
|
|
{
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Unknown handle index" , m_ThreadName ) ;
|
|
)
|
|
t_Status = FALSE ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return t_Status ;
|
|
}
|
|
|
|
ULONG SnmpThreadObject :: GetEventHandlesSize ()
|
|
{
|
|
return m_EventContainerLength ;
|
|
}
|
|
|
|
HANDLE *SnmpThreadObject :: GetEventHandles ()
|
|
{
|
|
return m_EventContainer ;
|
|
}
|
|
|
|
BOOL SnmpThreadObject :: ScheduleTask ( SnmpAbstractTaskObject &a_TaskObject )
|
|
{
|
|
BOOL t_Result = TRUE ;
|
|
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
|
|
/*
|
|
* Add Synchronous object to worker thread container
|
|
*/
|
|
a_TaskObject.m_ScheduledHandle = a_TaskObject.GetHandle ();
|
|
m_TaskContainer.Add ( &a_TaskObject ) ;
|
|
|
|
s_Lock.Unlock () ;
|
|
|
|
a_TaskObject.AttachTaskToThread ( *this ) ;
|
|
|
|
if ( GetCurrentThreadId () != m_ThreadId )
|
|
{
|
|
#if 0
|
|
SnmpEventObject t_ScheduledEventObject ;
|
|
|
|
EnterCriticalSectionWait ecs1 ( s_Lock ) ;
|
|
|
|
m_ScheduleReapEventContainer [ t_ScheduledEventObject.GetHandle () ] = &t_ScheduledEventObject ;
|
|
|
|
s_Lock.Unlock () ;
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ScheduleTask: Setting update" , m_ThreadName );
|
|
)
|
|
Set () ;
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ScheduleTask: Beginning Wait" , m_ThreadName );
|
|
)
|
|
|
|
if ( t_ScheduledEventObject.Wait () )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
t_Result = FALSE ;
|
|
}
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ScheduleTask: Ended Wait" , m_ThreadName );
|
|
)
|
|
|
|
EnterCriticalSectionWait ecs2 ( s_Lock ) ;
|
|
|
|
m_ScheduleReapEventContainer.RemoveKey ( t_ScheduledEventObject.GetHandle () ) ;
|
|
|
|
s_Lock.Unlock () ;
|
|
#else
|
|
Set () ;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
ConstructEventContainer () ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
BOOL SnmpThreadObject :: ReapTask ( SnmpAbstractTaskObject &a_TaskObject )
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Entering ReapTask [%lx]" , m_ThreadName , a_TaskObject.m_ScheduledHandle );
|
|
)
|
|
|
|
BOOL t_Result = TRUE ;
|
|
|
|
EnterCriticalSectionWait ecs ( s_Lock ) ;
|
|
|
|
/*
|
|
* Remove worker object from worker thread container
|
|
*/
|
|
|
|
POSITION t_Position = m_TaskContainer.GetHeadPosition () ;
|
|
while ( t_Position )
|
|
{
|
|
POSITION t_LastPosition = t_Position ;
|
|
SnmpAbstractTaskObject *t_TaskObject = m_TaskContainer.GetNext ( t_Position ) ;
|
|
if ( a_TaskObject.m_ScheduledHandle == t_TaskObject->m_ScheduledHandle )
|
|
{
|
|
m_TaskContainer.RemoveAt ( t_LastPosition ) ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
s_Lock.Unlock () ;
|
|
|
|
/*
|
|
* Inform worker thread,thread container has been updated.
|
|
*/
|
|
|
|
if ( GetCurrentThreadId () != m_ThreadId )
|
|
{
|
|
SnmpEventObject t_ReapedEventObject ;
|
|
|
|
EnterCriticalSectionWait ecs1 ( s_Lock ) ;
|
|
|
|
m_ScheduleReapEventContainer [ t_ReapedEventObject.GetHandle () ] = &t_ReapedEventObject ;
|
|
|
|
s_Lock.Unlock () ;
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ReapTask: Setting update" , m_ThreadName );
|
|
)
|
|
Set () ;
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ReapTask: Beginning Wait on [%lx]" , m_ThreadName , t_ReapedEventObject.GetHandle () );
|
|
)
|
|
|
|
if ( t_ReapedEventObject.Wait () )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
t_Result = FALSE ;
|
|
}
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ReapTask: Ended Wait" , m_ThreadName );
|
|
)
|
|
|
|
EnterCriticalSectionWait ecs2 ( s_Lock ) ;
|
|
|
|
m_ScheduleReapEventContainer.RemoveKey ( t_ReapedEventObject.GetHandle () ) ;
|
|
|
|
s_Lock.Unlock () ;
|
|
|
|
}
|
|
else
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ReapTask: ConstructEventContainer" , m_ThreadName );
|
|
)
|
|
ConstructEventContainer () ;
|
|
}
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Returning from ReapTask [%lx]" , m_ThreadName , a_TaskObject.m_ScheduledHandle );
|
|
)
|
|
|
|
a_TaskObject.DetachTaskFromThread ( *this ) ;
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
SnmpAbstractTaskObject :: SnmpAbstractTaskObject (
|
|
|
|
const wchar_t *a_GlobalTaskNameComplete,
|
|
const wchar_t *a_GlobalTaskNameAcknowledgement,
|
|
DWORD a_timeout
|
|
|
|
) : m_CompletionEvent ( a_GlobalTaskNameComplete ) ,
|
|
m_AcknowledgementEvent ( a_GlobalTaskNameAcknowledgement ) ,
|
|
m_timeout ( a_timeout ),
|
|
m_ScheduledHandle (NULL)
|
|
{
|
|
}
|
|
|
|
SnmpAbstractTaskObject :: ~SnmpAbstractTaskObject ()
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: ~SnmpAbstractTaskObject () [%lx]" , m_ScheduledHandle ) ;
|
|
)
|
|
EnterCriticalSectionWait ecs ( m_Lock ) ;
|
|
LeaveCriticalSectionScope lcs ( m_Lock );
|
|
|
|
if (NULL != m_ScheduledHandle)
|
|
{
|
|
POSITION t_Position = m_ThreadContainer.GetStartPosition () ;
|
|
while ( t_Position )
|
|
{
|
|
DWORD t_ThreadId ;
|
|
SnmpThreadObject *t_ThreadObject ;
|
|
m_ThreadContainer.GetNextAssoc ( t_Position , t_ThreadId , t_ThreadObject ) ;
|
|
|
|
t_ThreadObject->ReapTask ( *this ) ;
|
|
}
|
|
}
|
|
|
|
m_ThreadContainer.RemoveAll () ;
|
|
}
|
|
|
|
void SnmpAbstractTaskObject :: DetachTaskFromThread ( SnmpThreadObject &a_ThreadObject )
|
|
{
|
|
EnterCriticalSectionWait ecs ( m_Lock ) ;
|
|
LeaveCriticalSectionScope lcs ( m_Lock );
|
|
|
|
m_ThreadContainer.RemoveKey ( a_ThreadObject.GetThreadId () ) ;
|
|
}
|
|
|
|
void SnmpAbstractTaskObject :: AttachTaskToThread ( SnmpThreadObject &a_ThreadObject )
|
|
{
|
|
EnterCriticalSectionWait ecs ( m_Lock ) ;
|
|
LeaveCriticalSectionScope lcs ( m_Lock );
|
|
|
|
m_ThreadContainer [ a_ThreadObject.GetThreadId () ] = &a_ThreadObject ;
|
|
}
|
|
|
|
BOOL SnmpAbstractTaskObject :: Wait ( BOOL a_Dispatch )
|
|
{
|
|
BOOL t_Status = TRUE ;
|
|
BOOL t_Processed = FALSE ;
|
|
|
|
while ( t_Status && ! t_Processed )
|
|
{
|
|
SnmpThreadObject *t_ThreadObject = SnmpThreadObject :: GetThreadObject () ;
|
|
ULONG t_TaskEventArrayLength = 0 ;
|
|
HANDLE *t_TaskEventArray = NULL ;
|
|
|
|
if ( t_ThreadObject && a_Dispatch )
|
|
{
|
|
ULONG t_TaskArrayLength = t_ThreadObject->GetEventHandlesSize () ;
|
|
t_TaskEventArrayLength = t_TaskArrayLength + 1 ;
|
|
t_TaskEventArray = new HANDLE [ t_TaskEventArrayLength ] ;
|
|
|
|
if ( t_TaskEventArray )
|
|
{
|
|
t_TaskEventArray [ 0 ] = m_CompletionEvent.GetHandle () ;
|
|
|
|
memcpy (
|
|
|
|
& ( t_TaskEventArray [ 1 ] ) ,
|
|
t_ThreadObject->GetEventHandles () ,
|
|
t_TaskArrayLength * sizeof ( HANDLE )
|
|
) ;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_TaskEventArrayLength = 1 ;
|
|
t_TaskEventArray = new HANDLE [ t_TaskEventArrayLength ] ;
|
|
t_TaskEventArray [ 0 ] = m_CompletionEvent.GetHandle () ;
|
|
}
|
|
|
|
DWORD t_Event ;
|
|
|
|
if ( a_Dispatch )
|
|
{
|
|
t_Event = MsgWaitForMultipleObjects (
|
|
|
|
t_TaskEventArrayLength ,
|
|
t_TaskEventArray ,
|
|
FALSE ,
|
|
m_timeout ,
|
|
QS_ALLINPUT
|
|
) ;
|
|
}
|
|
else
|
|
{
|
|
t_Event = WaitForMultipleObjects (
|
|
|
|
t_TaskEventArrayLength ,
|
|
t_TaskEventArray ,
|
|
FALSE ,
|
|
m_timeout
|
|
) ;
|
|
}
|
|
|
|
ULONG t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
|
|
|
|
if ( t_Event == 0xFFFFFFFF )
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle" ) ;
|
|
)
|
|
|
|
DWORD t_Error = GetLastError () ;
|
|
t_Status = FALSE ;
|
|
}
|
|
else if ( t_Event == WAIT_TIMEOUT)
|
|
{
|
|
TimedOut();
|
|
}
|
|
else if ( t_HandleIndex == t_TaskEventArrayLength )
|
|
{
|
|
BOOL t_DispatchStatus ;
|
|
MSG t_Msg ;
|
|
|
|
while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
|
|
{
|
|
int t_Result = 0;
|
|
t_Result = GetMessage ( & t_Msg , NULL , 0 , 0 );
|
|
|
|
if ( t_Result != 0 && t_Result != -1 )
|
|
{
|
|
TranslateMessage ( & t_Msg ) ;
|
|
DispatchMessage ( & t_Msg ) ;
|
|
}
|
|
|
|
BOOL t_Timeout = FALSE ;
|
|
|
|
while ( ! t_Timeout && t_Status && ! t_Processed )
|
|
{
|
|
t_Event = WaitForMultipleObjects (
|
|
|
|
t_TaskEventArrayLength ,
|
|
t_TaskEventArray ,
|
|
FALSE ,
|
|
0
|
|
) ;
|
|
|
|
t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
|
|
|
|
if ( t_Event == 0xFFFFFFFF )
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle" ) ;
|
|
)
|
|
|
|
DWORD t_Error = GetLastError () ;
|
|
t_Status = FALSE ;
|
|
}
|
|
else if ( t_Event == WAIT_TIMEOUT)
|
|
{
|
|
t_Timeout = TRUE ;
|
|
}
|
|
else if ( t_HandleIndex < t_TaskEventArrayLength )
|
|
{
|
|
HANDLE t_Handle = t_TaskEventArray [ t_HandleIndex ] ;
|
|
t_Status = WaitDispatch ( t_ThreadObject , t_Handle , t_Processed ) ;
|
|
}
|
|
else
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle index" ) ;
|
|
)
|
|
t_Status = FALSE ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( t_HandleIndex < t_TaskEventArrayLength )
|
|
{
|
|
HANDLE t_Handle = t_TaskEventArray [ t_HandleIndex ] ;
|
|
t_Status = WaitDispatch ( t_ThreadObject , t_Handle , t_Processed ) ;
|
|
}
|
|
else
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle index" ) ;
|
|
)
|
|
|
|
t_Status = FALSE ;
|
|
}
|
|
|
|
delete [] t_TaskEventArray ;
|
|
}
|
|
|
|
return t_Status ;
|
|
}
|
|
|
|
BOOL SnmpAbstractTaskObject :: WaitDispatch ( SnmpThreadObject *a_ThreadObject, HANDLE a_Handle , BOOL &a_Processed )
|
|
{
|
|
BOOL t_Status = TRUE ;
|
|
|
|
if ( a_Handle == m_CompletionEvent.GetHandle () )
|
|
{
|
|
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nWait: Completed" );
|
|
)
|
|
|
|
|
|
m_CompletionEvent.Process () ;
|
|
a_Processed = TRUE ;
|
|
}
|
|
else if ( a_ThreadObject && ( a_Handle == a_ThreadObject->GetHandle () ) )
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nTask Wait: Refreshing handles" );
|
|
)
|
|
a_ThreadObject->Process () ;
|
|
a_ThreadObject->ConstructEventContainer () ;
|
|
}
|
|
else
|
|
{
|
|
SnmpAbstractTaskObject *t_TaskObject = a_ThreadObject->GetTaskObject ( a_Handle ) ;
|
|
if ( t_TaskObject )
|
|
{
|
|
a_ThreadObject->RotateTask ( t_TaskObject ) ;
|
|
a_ThreadObject->ConstructEventContainer () ;
|
|
t_TaskObject->Process () ;
|
|
}
|
|
else
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Task" ) ;
|
|
)
|
|
t_Status = FALSE ;
|
|
}
|
|
}
|
|
|
|
return t_Status ;
|
|
}
|
|
|
|
BOOL SnmpAbstractTaskObject :: WaitAcknowledgement ( BOOL a_Dispatch )
|
|
{
|
|
BOOL t_Status = TRUE ;
|
|
BOOL t_Processed = FALSE ;
|
|
|
|
while ( t_Status && ! t_Processed )
|
|
{
|
|
SnmpThreadObject *t_ThreadObject = SnmpThreadObject :: GetThreadObject () ;
|
|
ULONG t_TaskEventArrayLength = 0 ;
|
|
HANDLE *t_TaskEventArray = NULL ;
|
|
|
|
if ( t_ThreadObject && a_Dispatch )
|
|
{
|
|
ULONG t_TaskArrayLength = t_ThreadObject->GetEventHandlesSize () ;
|
|
t_TaskEventArrayLength = t_TaskArrayLength + 1 ;
|
|
t_TaskEventArray = new HANDLE [ t_TaskEventArrayLength ] ;
|
|
|
|
if ( t_TaskArrayLength )
|
|
{
|
|
memcpy (
|
|
|
|
& ( t_TaskEventArray [ 1 ] ) ,
|
|
t_ThreadObject->GetEventHandles () ,
|
|
t_TaskArrayLength * sizeof ( HANDLE )
|
|
) ;
|
|
}
|
|
|
|
t_TaskEventArray [ 0 ] = m_AcknowledgementEvent.GetHandle () ;
|
|
}
|
|
else
|
|
{
|
|
t_TaskEventArrayLength = 1 ;
|
|
t_TaskEventArray = new HANDLE [ t_TaskEventArrayLength ] ;
|
|
t_TaskEventArray [ 0 ] = m_AcknowledgementEvent.GetHandle () ;
|
|
}
|
|
|
|
DWORD t_Event ;
|
|
|
|
if ( a_Dispatch )
|
|
{
|
|
t_Event = MsgWaitForMultipleObjects (
|
|
|
|
t_TaskEventArrayLength ,
|
|
t_TaskEventArray ,
|
|
FALSE ,
|
|
m_timeout ,
|
|
QS_ALLINPUT
|
|
) ;
|
|
}
|
|
else
|
|
{
|
|
t_Event = WaitForMultipleObjects (
|
|
|
|
t_TaskEventArrayLength ,
|
|
t_TaskEventArray ,
|
|
FALSE ,
|
|
m_timeout
|
|
) ;
|
|
}
|
|
|
|
ULONG t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
|
|
|
|
if ( t_Event == 0xFFFFFFFF )
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle" ) ;
|
|
)
|
|
|
|
DWORD t_Error = GetLastError () ;
|
|
t_Status = FALSE ;
|
|
}
|
|
else if ( t_Event == WAIT_TIMEOUT)
|
|
{
|
|
TimedOut();
|
|
}
|
|
if ( t_HandleIndex == t_TaskEventArrayLength )
|
|
{
|
|
BOOL t_DispatchStatus ;
|
|
MSG t_Msg ;
|
|
|
|
while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
|
|
{
|
|
int t_Result = 0;
|
|
t_Result = GetMessage ( & t_Msg , NULL , 0 , 0 );
|
|
|
|
if ( t_Result != 0 && t_Result != -1 )
|
|
{
|
|
TranslateMessage ( & t_Msg ) ;
|
|
DispatchMessage ( & t_Msg ) ;
|
|
}
|
|
|
|
BOOL t_Timeout = FALSE ;
|
|
|
|
while ( ! t_Timeout && t_Status && ! t_Processed )
|
|
{
|
|
t_Event = WaitForMultipleObjects (
|
|
|
|
t_TaskEventArrayLength ,
|
|
t_TaskEventArray ,
|
|
FALSE ,
|
|
0
|
|
) ;
|
|
|
|
ULONG t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
|
|
|
|
if ( t_Event == 0xFFFFFFFF )
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle" ) ;
|
|
)
|
|
|
|
DWORD t_Error = GetLastError () ;
|
|
t_Status = FALSE ;
|
|
}
|
|
else if ( t_Event == WAIT_TIMEOUT)
|
|
{
|
|
t_Timeout = TRUE ;
|
|
}
|
|
else if ( t_HandleIndex < t_TaskEventArrayLength )
|
|
{
|
|
HANDLE t_Handle = t_TaskEventArray [ t_HandleIndex ] ;
|
|
t_Status = WaitAcknowledgementDispatch ( t_ThreadObject , t_Handle , t_Processed ) ;
|
|
}
|
|
else
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle index" ) ;
|
|
)
|
|
t_Status = FALSE ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( t_HandleIndex < t_TaskEventArrayLength )
|
|
{
|
|
HANDLE t_Handle = t_TaskEventArray [ t_HandleIndex ] ;
|
|
t_Status = WaitAcknowledgementDispatch ( t_ThreadObject , t_Handle , t_Processed ) ;
|
|
}
|
|
else
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle index" ) ;
|
|
)
|
|
|
|
t_Status = FALSE ;
|
|
}
|
|
|
|
delete [] t_TaskEventArray ;
|
|
}
|
|
|
|
return t_Status ;
|
|
}
|
|
|
|
BOOL SnmpAbstractTaskObject :: WaitAcknowledgementDispatch ( SnmpThreadObject *a_ThreadObject , HANDLE a_Handle , BOOL &a_Processed )
|
|
{
|
|
BOOL t_Status = TRUE ;
|
|
|
|
if ( a_Handle == m_AcknowledgementEvent.GetHandle () )
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nWait: Completed" );
|
|
)
|
|
|
|
m_AcknowledgementEvent.Process () ;
|
|
a_Processed = TRUE ;
|
|
}
|
|
else if ( a_ThreadObject && ( a_Handle == a_ThreadObject->GetHandle () ) )
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nTask Wait: Refreshing handles" );
|
|
)
|
|
a_ThreadObject->Process () ;
|
|
a_ThreadObject->ConstructEventContainer () ;
|
|
}
|
|
else
|
|
{
|
|
SnmpAbstractTaskObject *t_TaskObject = a_ThreadObject->GetTaskObject ( a_Handle ) ;
|
|
if ( t_TaskObject )
|
|
{
|
|
a_ThreadObject->RotateTask ( t_TaskObject ) ;
|
|
a_ThreadObject->ConstructEventContainer () ;
|
|
t_TaskObject->Process () ;
|
|
}
|
|
else
|
|
{
|
|
DebugMacro8(
|
|
|
|
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Task" ) ;
|
|
)
|
|
t_Status = FALSE ;
|
|
}
|
|
}
|
|
|
|
return t_Status ;
|
|
}
|
|
|
|
SnmpTaskObject::SnmpTaskObject (
|
|
const wchar_t *a_GlobalTaskNameStart,
|
|
const wchar_t *a_GlobalTaskNameComplete ,
|
|
const wchar_t *a_GlobalTaskNameAcknowledge,
|
|
DWORD a_timeout
|
|
|
|
): SnmpAbstractTaskObject(a_GlobalTaskNameComplete, a_GlobalTaskNameAcknowledge,a_timeout), m_Event(a_GlobalTaskNameStart)
|
|
{
|
|
}
|