text: // Copyright (c) 1997, Microsoft Corporation, all rights reserved
  //
  // timer.h
  // RAS L2TP WAN mini-port/call-manager driver
  // Timer management header
  //
  // 01/07/97 Steve Cobb
  //
  // This interface encapsulates the queuing of multiple timer events onto a
  // single NDIS timer.
  
  
  #ifndef _TIMER_H_
  #define _TIMER_H_
  
  
  //-----------------------------------------------------------------------------
  // Data structures
  //-----------------------------------------------------------------------------
  
  // Forward declarations.
  //
  typedef struct _TIMERQ TIMERQ;
  typedef struct _TIMERQITEM TIMERQITEM;
  typedef enum _TIMERQEVENT TIMERQEVENT;
  
  
  // Timer queue event handler.  'PTqi' and 'pContext' are the timer event
  // descriptor and user context passed to TimerQScheduleItem.  'Event' is the
  // timer event code indicating whether the timer expired, was cancelled, or
  // the queue was terminated.
  //
  // The "cancel" event is never generated internally, but only by a user call
  // to TimerQCancelItem, thus user may require specific locks be held for
  // "cancel" events.  User cannot require than specific locks be held for
  // "expire" or "terminate" events as these may be generated internally.  User
  // should pay attention to the return codes of TimerQCancelItem and
  // TimerQTerminateItem calls, as it will occassionally be impossible to stop
  // an "expire" event that has not yet been processed from occurring.
  //
  typedef
  VOID
  (*PTIMERQEVENT)(
      IN TIMERQITEM* pTqi,
      IN VOID* pContext,
      IN TIMERQEVENT event );
  
  // Timer queue termination completion handler.  'PTimerQ' is the timer queue
  // descriptor.  'PContext' is user's context as passed to TimerQTerminate.
  // Caller must not free or reuse the TIMERQ before this routine is called.
  //
  typedef
  VOID
  (*PTIMERQTERMINATECOMPLETE)(
      IN TIMERQ* pTimerQ,
      IN VOID* pContext );
  
  
  // Timer queue descriptor.  All access should be via the TimerQ* interface.
  // There is no reason user should look inside.  All necessary locking is
  // handled internally.
  //
  typedef struct
  _TIMERQ
  {
      // Set to MTAG_TIMERQ when the block is valid and to MTAG_FREED when no
      // longer valid.
      //
      ULONG ulTag;
  
      // Head of a double-linked list of "ticking" TIMERQITEMs.  The list is
      // sorted by time to expiration with the earliest expiration at the head
      // of the list.  The list is protected by 'lock'.
      //
      LIST_ENTRY listItems;
  
      // Caller's terminate complete handler as passed to TimerQTerminate.  This
      // is non-NULL only when our internal timer event handler must call it.
      //
      PTIMERQTERMINATECOMPLETE pHandler;
  
      // User's PTIMERQTERMINATECOMPLETE context passed back to 'pHandler'.
      //
      VOID* pContext;
  
      // Set when the timer queue is terminating.  No other requests are
      // accepted when this is the case.
      //
      BOOLEAN fTerminating;
  
      // Spin lock protecting the 'listItems' list.
      //
      NDIS_SPIN_LOCK lock;
  
      // NDIS timer object.
      //
      NDIS_TIMER timer;
  }
  TIMERQ;
  
  
  // Timer queue event descriptor.  All access should be via the TimerQ*
  // interface.  There is no reason user should look inside.  This is exposed to
  // allow user to efficiently manage allocation of TIMERQITEMS for several
  // timers from a large pool.
  //
  typedef struct
  _TIMERQITEM
  {
      // Links to the prev/next TIMERQITEM in the owning TIMERQ's chain of
      // pending timer events.  Access is protected by 'lock' in the TIMERQ
      // structure.
      //
      LIST_ENTRY linkItems;
  
      // System time at which this event should occur.
      //
      LONGLONG llExpireTime;
  
      // User's routine to handle the timeout event when it occurs.
      //
      PTIMERQEVENT pHandler;
  
      // User's PTIMERQEVENT context passed back to 'pHandler'.
      //
      VOID* pContext;
  }
  TIMERQITEM;
  
  
  // Indicates the event which triggered user's callback to be called.
  //
  typedef enum
  _TIMERQEVENT
  {
      // The timeout interval has elapsed or user called TimerQExpireItem.
      //
      TE_Expire,
  
      // User called TimerQCancelItem.
      //
      TE_Cancel,
  
      // User called TimerQTerminateItem or called TimerQTerminate while the
      // item was queued.
      //
      TE_Terminate
  }
  TIMERQEVENT;
  
  
  //-----------------------------------------------------------------------------
  // Interface prototypes
  //-----------------------------------------------------------------------------
  
  BOOLEAN
  IsTimerQItemScheduled(
      IN TIMERQITEM* pItem );
  
  VOID
  TimerQInitialize(
      IN TIMERQ* pTimerQ );
  
  VOID
  TimerQInitializeItem(
      IN TIMERQITEM* pItem );
  
  VOID
  TimerQTerminate(
      IN TIMERQ* pTimerQ,
      IN PTIMERQTERMINATECOMPLETE pHandler,
      IN VOID* pContext );
  
  VOID
  TimerQScheduleItem(
      IN TIMERQ* pTimerQ,
      IN OUT TIMERQITEM* pNewItem,
      IN ULONG ulTimeoutMs,
      IN PTIMERQEVENT pHandler,
      IN VOID* pContext );
  
  BOOLEAN
  TimerQCancelItem(
      IN TIMERQ* pTimerQ,
      IN TIMERQITEM* pItem );
  
  BOOLEAN
  TimerQExpireItem(
      IN TIMERQ* pTimerQ,
      IN TIMERQITEM* pItem );
  
  CHAR*
  TimerQPszFromEvent(
      IN TIMERQEVENT event );
  
  BOOLEAN
  TimerQTerminateItem(
      IN TIMERQ* pTimerQ,
      IN TIMERQITEM* pItem );
  
  
  #endif // TIMER_H_
  