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.
143 lines
4.5 KiB
143 lines
4.5 KiB
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
MERGERTHROTTLING.H
|
|
|
|
Abstract:
|
|
|
|
CMergerThrottling clas
|
|
|
|
History:
|
|
|
|
30-Nov-00 sanjes Created.
|
|
|
|
--*/
|
|
|
|
#ifndef _MERGERTHROTTLING_H_
|
|
#define _MERGERTHROTTLING_H_
|
|
|
|
// Enables debug messages for additional info.
|
|
#ifdef DBG
|
|
//#define __DEBUG_MERGER_THROTTLING
|
|
#endif
|
|
|
|
// Defaults - can be overridden from the registry
|
|
#define DEFAULT_THROTTLE_THRESHOLD 10
|
|
#define DEFAULT_THROTTLE_RELEASE_THRESHOLD 4
|
|
|
|
// Forward Class Definitions
|
|
class CInternalMerger;
|
|
class CWmiMergerRecord;
|
|
|
|
// This class encapsulates the throttling behavior which will be used by the internal
|
|
// merger in order to control delivery of parent and child objects.
|
|
|
|
class CMergerThrottling
|
|
{
|
|
// Following members are used for throttling incoming objects so that our
|
|
// parent and child objects don't get wildly out of control. Note that we
|
|
// use separate throttling events, since the decision to throttle is made in
|
|
// a critsec, but the actual throttling occurs outside. This can have the
|
|
// unpleasant side effect of a race condition in which for example, the parent
|
|
// decides to throttle, steps out of the critsec, and a context switch occurs,
|
|
// in which the child gets a large number of objects, releases the throttle, but
|
|
// then causes child throttling to occur, resetting the event. If the parent
|
|
// thread switches in at this point, we're hosed, since we will now wait on the
|
|
// parent and the child.
|
|
|
|
HANDLE m_hParentThrottlingEvent;
|
|
HANDLE m_hChildThrottlingEvent;
|
|
|
|
DWORD m_dwNumChildObjects;
|
|
DWORD m_dwNumParentObjects;
|
|
DWORD m_dwNumThrottledThreads;
|
|
|
|
// Contains the time of the last ping from a parent or child.
|
|
// Used to calculate whether or not we timeout
|
|
DWORD m_dwLastParentPing;
|
|
DWORD m_dwLastChildPing;
|
|
|
|
// These should NEVER both be TRUE
|
|
bool m_bParentThrottled;
|
|
bool m_bChildThrottled;
|
|
|
|
// Stop us from throttling if one side or the other is done
|
|
bool m_bParentDone;
|
|
bool m_bChildDone;
|
|
|
|
// This controls the point where we determine that we need to perform throttling
|
|
// Once parent or children are > m_dwThrottlingThreshold objects apart, one or the
|
|
// other will be throttled
|
|
DWORD m_dwThrottlingThreshold;
|
|
|
|
// This controls the threshold where we will release currently throttled threads
|
|
// Once we are throttled, we will remain throttled until parent or children are <
|
|
// m_dwReleaseThreshold objects out of sync with each other.
|
|
DWORD m_dwReleaseThreshold;
|
|
|
|
// This controls the amount of memory we will allow Indicates to process before
|
|
// forcing them to send objects further down the line
|
|
DWORD m_dwBatchingThreshold;
|
|
|
|
// This controls the timeout value we wait for. If we timeout and a provider has
|
|
// not pinged us in the specified timeout, then we will cancel the merger with
|
|
// a provider timed out error.
|
|
DWORD m_dwProviderDeliveryTimeout;
|
|
|
|
// We will expose this for other synchronization activities
|
|
CCritSec m_cs;
|
|
|
|
// Helper functions to control throttling
|
|
bool ShouldThrottle( bool bParent );
|
|
HRESULT PrepareThrottle( bool bParent, HANDLE* phEvent );
|
|
bool VerifyTimeout( DWORD dwLastTick, long lNumArbThrottledThreads, DWORD* pdwAdjust );
|
|
|
|
public:
|
|
|
|
CMergerThrottling();
|
|
~CMergerThrottling();
|
|
|
|
// Two stage initialization
|
|
HRESULT Initialize( void );
|
|
|
|
// Returns TRUE if throttling occurred
|
|
HRESULT Throttle( bool bParent, CWmiMergerRecord* pMergerRecord );
|
|
|
|
// Returns TRUE if we released throttled threads.
|
|
bool ReleaseThrottle( bool bForce = false );
|
|
|
|
// Informs us that we are in fact, done with Child and/or Parent
|
|
void SetChildrenDone( void );
|
|
void SetParentDone( void );
|
|
void Cancel( void );
|
|
|
|
// Helpers to control the number of current parent and child objects
|
|
// which we will then use to make decisions as to whether or not
|
|
// we should block a thread or not
|
|
DWORD AdjustNumParentObjects( long lNumParentObjects )
|
|
{ return ( m_dwNumParentObjects += lNumParentObjects ); }
|
|
DWORD AdjustNumChildObjects( long lNumChildObjects )
|
|
{ return ( m_dwNumChildObjects += lNumChildObjects ); }
|
|
|
|
// Access to our critical section
|
|
void Enter( void ) { m_cs.Enter(); }
|
|
void Leave( void ) { m_cs.Leave(); }
|
|
|
|
// Adjusts ping times
|
|
DWORD Ping( bool bParent, CWmiMerger* pWmiMerger );
|
|
|
|
CCritSec* GetCritSec( void ) { return &m_cs; }
|
|
|
|
// Checks batch size against our limit
|
|
bool IsCompleteBatch( long lBatchSize ) { return lBatchSize >= m_dwBatchingThreshold; }
|
|
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|