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.
 
 
 
 
 
 

468 lines
12 KiB

// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
/*---------------------------------------------------------
Filename: timer.cpp
Written By: B.Rajeev
----------------------------------------------------------*/
#include "precomp.h"
#include "common.h"
#include "sync.h"
#include "timer.h"
#include "message.h"
#include "dummy.h"
#include "flow.h"
#include "frame.h"
#include "ssent.h"
#include "idmap.h"
#include "opreg.h"
#include "session.h"
SnmpClThreadObject *Timer :: g_timerThread = NULL ;
UINT Timer :: g_SnmpWmTimer = SNMP_WM_TIMER ;
// static CriticalSection and CMap
CriticalSection Timer::timer_CriticalSection;
TimerMapping Timer::timer_mapping;
TimerEventId Timer :: next_timer_event_id = ILLEGAL_TIMER_EVENT_ID+1 ;
Window *SnmpTimerObject :: window = NULL ;
CMap <UINT_PTR,UINT_PTR,SnmpTimerObject *,SnmpTimerObject *> SnmpTimerObject :: timerMap ;
SnmpClThreadObject :: SnmpClThreadObject () : SnmpThreadObject ( "SnmpCl" )
{
}
void SnmpClThreadObject :: Initialise ()
{
}
void SnmpClThreadObject :: Uninitialise ()
{
delete SnmpTimerObject :: window ;
SnmpTimerObject :: window = NULL ;
delete this ;
}
SnmpClTrapThreadObject :: SnmpClTrapThreadObject () : SnmpThreadObject ( "SnmpClTrapThread" )
{
}
void SnmpClTrapThreadObject :: Initialise ()
{
DebugMacro4(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine (
__FILE__,__LINE__,
L"SnmpClTrapThreadObject::Initialise: Initialised!!\n"
) ;
)
}
void SnmpClTrapThreadObject :: Uninitialise ()
{
DebugMacro4(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine (
__FILE__,__LINE__,
L"SnmpClTrapThreadObject::Uninitialise: About to destroy trap thread\n"
) ;
)
delete this ;
DebugMacro4(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine (
__FILE__,__LINE__,
L"SnmpClTrapThreadObject::Uninitialise: Trap thread destroyed!!\n"
) ;
)
}
Timer::Timer(SnmpImpSession &session)
{
Timer::session = &session;
}
BOOL Timer::CreateCriticalSection()
{
return TRUE;
}
void Timer::DestroyCriticalSection()
{
}
BOOL Timer::InitializeStaticComponents()
{
return CreateCriticalSection();
}
void Timer::DestroyStaticComponents()
{
DestroyCriticalSection();
}
// generates and returns a new event id
// associates the pair (event_id, waiting_message)
// creates the timer event
TimerEventId Timer::SetTimerEvent(UINT timeout_value)
{
TimerEventId suggested_event_id = next_timer_event_id++;
if ( suggested_event_id == ILLEGAL_TIMER_EVENT_ID )
suggested_event_id = next_timer_event_id++;
// let the dummy session receive the window messages for timer events
TimerEventId event_id =
SnmpSetTimer( session->m_SessionWindow.GetWindowHandle(), suggested_event_id,
timeout_value, NULL );
if ( (event_id == ILLEGAL_TIMER_EVENT_ID) ||
(event_id != suggested_event_id) )
throw GeneralException(Snmp_Error, Snmp_Local_Error,__FILE__,__LINE__);
return event_id;
}
// generates and returns a new event id
// associates the pair (event_id, waiting_message)
// creates the timer event
void Timer::SetMessageTimerEvent(WaitingMessage &waiting_message)
{
CriticalSectionLock session_lock(session->session_CriticalSection);
if ( !session_lock.GetLock(INFINITE) )
return; // no use throwing exception
TimerEventId event_id = session->timer_event_id;
// register the timer event in both the instance CMap and the global CMap
waiting_message_mapping.AddTail ( &waiting_message ) ;
session_lock.UnLock();
CriticalSectionLock timer_lock(Timer::timer_CriticalSection);
if ( !timer_lock.GetLock(INFINITE) )
throw GeneralException ( Snmp_Error , Snmp_Local_Error,__FILE__,__LINE__ ) ;
timer_mapping[event_id] = this;
timer_lock.UnLock();
}
// Removes the association (event_id, waiting_message)
// and also kills the registered timer event
void Timer::CancelMessageTimer(WaitingMessage &waiting_message,TimerEventId event_id)
{
CriticalSectionLock session_lock(session->session_CriticalSection);
if ( !session_lock.GetLock(INFINITE) )
return; // no use throwing exception
// remove the timer event from the instance CMap
POSITION t_Position = waiting_message_mapping.GetHeadPosition () ;
while ( t_Position )
{
POSITION t_OldPosition = t_Position ;
WaitingMessage *t_Message = waiting_message_mapping.GetNext ( t_Position ) ;
if ( t_Message == & waiting_message )
{
waiting_message_mapping.RemoveAt(t_OldPosition);
break ;
}
}
session_lock.UnLock();
DebugMacro4(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine (
__FILE__,__LINE__,
L"Cancelled Message TimerEvent %d\n", event_id
) ;
)
}
// Removes the association (event_id, waiting_message)
// and also kills the registered timer event
void Timer::CancelTimer(TimerEventId event_id)
{
CriticalSectionLock timer_lock(Timer::timer_CriticalSection);
if ( !timer_lock.GetLock(INFINITE) )
throw GeneralException ( Snmp_Error , Snmp_Local_Error,__FILE__,__LINE__ ) ;
// remove the timer event from the global CMap
timer_mapping.RemoveKey(event_id);
timer_lock.UnLock();
SnmpKillTimer(NULL, event_id);
DebugMacro4(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine (
__FILE__,__LINE__,
L"Cancelled TimerEvent %d\n", event_id
) ;
)
}
// it determines the corresponding Timer and calls
// its TimerEventNotification with the appropriate parameters
void CALLBACK Timer::HandleGlobalEvent(HWND hWnd ,UINT message,
UINT_PTR idEvent, DWORD dwTime)
{
CriticalSectionLock timer_lock(Timer::timer_CriticalSection);
if ( !timer_lock.GetLock(INFINITE) )
throw GeneralException ( Snmp_Error , Snmp_Local_Error,__FILE__,__LINE__ ) ;
Timer *timer;
TimerEventId event_id = idEvent;
BOOL found = timer_mapping.Lookup(event_id, timer);
timer_lock.UnLock();
// if no such timer event, return
if ( !found )
return;
// let the timer handle the event
timer->TimerEventNotification(event_id);
return;
}
// used by the event handler to notify the timer event.
// it must notify the corresponding waiting message
void Timer::TimerEventNotification(TimerEventId event_id)
{
CriticalSectionLock session_lock(session->session_CriticalSection);
if ( !session_lock.GetLock(INFINITE) )
return; // no use throwing exception
WaitingMessage *waiting_message;
// identify the waiting message corresponding to
// the event_id. if no such event, ignore it
POSITION t_Position = waiting_message_mapping.GetHeadPosition () ;
while ( t_Position )
{
waiting_message = waiting_message_mapping.GetNext ( t_Position ) ;
// notify the waiting message of the event
waiting_message->TimerNotification();
}
// session_lock.UnLock(); The lock may be released at this point
}
// remove all the (timer_event_id, timer) associations
// from the static mapping data structure
Timer::~Timer(void)
{
WaitingMessage *waiting_message;
POSITION current = waiting_message_mapping.GetHeadPosition();
while ( current != NULL )
{
waiting_message = waiting_message_mapping.GetNext(current);
TimerEventId event_id = waiting_message->GetTimerEventId () ;
CriticalSectionLock timer_lock(Timer::timer_CriticalSection);
if ( !timer_lock.GetLock(INFINITE) )
throw GeneralException ( Snmp_Error , Snmp_Local_Error,__FILE__,__LINE__ ) ;
timer_mapping.RemoveKey ( event_id );
timer_lock.UnLock();
SnmpKillTimer(NULL, event_id );
}
waiting_message_mapping.RemoveAll();
}
SnmpTimerObject :: SnmpTimerObject (
HWND hWndArg, // handle of window for timer messages
UINT_PTR timerIdArg, // timer identifier
UINT elapsedArg, // time-out value
TIMERPROC lpTimerFuncArg // address of timer procedure
) : hWnd ( hWndArg ) ,
timerId ( timerIdArg ) ,
lpTimerFunc ( lpTimerFuncArg )
{
if ( ! window )
window = new Window ;
timerId = SetTimer (
window->GetWindowHandle(),
timerId ,
elapsedArg ,
lpTimerFunc
) ;
CriticalSectionLock session_lock(Timer::timer_CriticalSection);
if ( !session_lock.GetLock(INFINITE) )
throw GeneralException ( Snmp_Error , Snmp_Local_Error,__FILE__,__LINE__ ) ;
if ( timerId )
{
timerMap [ timerId ] = this ;
}
else
throw GeneralException ( Snmp_Error , Snmp_Local_Error,__FILE__,__LINE__ ) ;
}
SnmpTimerObject :: ~SnmpTimerObject ()
{
CriticalSectionLock session_lock(Timer::timer_CriticalSection);
if ( !session_lock.GetLock(INFINITE) )
throw GeneralException ( Snmp_Error , Snmp_Local_Error,__FILE__,__LINE__ ) ;
timerMap.RemoveKey ( timerId );
if (window)
{
KillTimer ( window->GetWindowHandle () , timerId ) ;
}
}
void SnmpTimerObject :: TimerNotification ( HWND hWnd , UINT timerId )
{
:: WaitPostMessage ( hWnd , Timer :: g_SnmpWmTimer , timerId , 0 ) ;
}
SnmpSetTimerObject :: SnmpSetTimerObject (
HWND hWndArg, // handle of window for timer messages
UINT_PTR nIDEventArg, // timer identifier
UINT uElapseArg, // time-out value
TIMERPROC lpTimerFuncArg // address of timer procedure
) : hWnd ( hWndArg ) ,
timerId ( nIDEventArg ) ,
elapsedTime ( uElapseArg ) ,
lpTimerFunc ( lpTimerFuncArg )
{
}
SnmpSetTimerObject :: ~SnmpSetTimerObject ()
{
}
void SnmpSetTimerObject :: Process ()
{
SnmpTimerObject *object = new SnmpTimerObject (
hWnd ,
timerId ,
elapsedTime ,
lpTimerFunc
) ;
Complete () ;
}
SnmpKillTimerObject :: SnmpKillTimerObject (
HWND hWndArg , // handle of window that installed timer
UINT_PTR uIDEventArg // timer identifier
) : hWnd ( hWndArg ) ,
timerId ( uIDEventArg ) ,
status ( TRUE )
{
}
void SnmpKillTimerObject :: Process ()
{
CriticalSectionLock session_lock(Timer::timer_CriticalSection);
if ( !session_lock.GetLock(INFINITE) )
throw GeneralException ( Snmp_Error , Snmp_Local_Error,__FILE__,__LINE__ ) ;
SnmpTimerObject *object ;
if ( SnmpTimerObject :: timerMap.Lookup ( timerId , object ) )
{
delete object ;
}
else
{
status = FALSE ;
}
Complete () ;
}
UINT_PTR SnmpSetTimer (
HWND hWnd, // handle of window for timer messages
UINT_PTR nIDEvent, // timer identifier
UINT uElapse, // time-out value,
TIMERPROC lpTimerFunc // address of timer procedure
)
{
SnmpSetTimerObject object ( hWnd , nIDEvent , uElapse , lpTimerFunc ) ;
Timer :: g_timerThread->ScheduleTask ( object ) ;
object.Exec () ;
if ( object.Wait () )
{
Timer :: g_timerThread->ReapTask ( object ) ;
return object.GetTimerId () ;
}
else
{
Timer :: g_timerThread->ReapTask ( object ) ;
return FALSE ;
}
}
BOOL SnmpKillTimer (
HWND hWnd, // handle of window that installed timer
UINT_PTR uIDEvent // timer identifier
)
{
SnmpKillTimerObject object ( hWnd , uIDEvent ) ;
Timer :: g_timerThread->ScheduleTask ( object ) ;
object.Exec () ;
if ( object.Wait () )
{
Timer :: g_timerThread->ReapTask ( object ) ;
return object.GetStatus () ;
}
else
{
Timer :: g_timerThread->ReapTask ( object ) ;
return FALSE ;
}
}