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.
|
|
//=================================================================
//
// ResourceManager.cpp
//
// Copyright (c) 1998-2002 Microsoft Corporation, All Rights Reserved
//
//=================================================================
/*
* Currently the implementations of std::_Lockit::_Lockit() are in framedyn.dll * If this class is being used outside the scope of win32providers then an implementation of std::_Lockit::_Lockit() has to be provided * by the client ( I think!) . */
#include "precomp.h"
#include <assertbreak.h>
#include "ResourceManager.h"
#include "ProvExce.h"
#include <comdef.h>
#include "TimerQueue.h"
// automatic crit sec
#include "cautolock.h"
//
// resource management failures
//
BOOL bAddInstanceCreatorFailure = FALSE ;
//initialize statics
/*
* All the resources not released by clients or cached in the ResourceManager are forcibly freed in the ResourceManager destructor. * When a resource is freed , the resource tries to deregister the timeout rule from the TimerQueue, which means that the TimerQueue * has to be present when the ResourceManager destructor is fired,else we'll have a crash on Win9x. --RAID 50454 */ //CTimerQueue CTimerQueue :: s_TimerQueue ;
//CResourceManager CResourceManager::sm_TheResourceManager ;
CResourceManager :: CResourceManager () { }
CResourceManager :: ~CResourceManager () { std::list < CResourceList* >::iterator pInstanceList ; /*
* Ideally, at this point of time when the global destructors get fired there should not be any resources in the resource manager, * but if there are any , we've to forcibly delete them. We're safe in doing this becuase the scheduler thread would've exited already * in DllCanUnloadNow & no other thread would be calling into the resource manager */ LogMessage ( L"Entering ~CResourceManager" ) ;
CAutoLock cs ( m_csResourceManager ) ; while ( !m_Resources.empty () ) { delete m_Resources.front() ; m_Resources.pop_front() ; } cs.Exec () ; LogMessage ( L"Leaving ~CResourceManager" ) ; }
/*
* This method checks if we've any resource leak */ void CResourceManager :: ForcibleCleanUp () { LogMessage ( L"Entering CResourceManager :: ForcibleCleanUp" ) ; std::list < CResourceList* >::iterator pInstanceList ;
CAutoLock cs ( m_csResourceManager ) ; for ( pInstanceList = m_Resources.begin () ; pInstanceList != m_Resources.end () ; pInstanceList++ ) { ( *pInstanceList )->ShutDown () ; } cs.Exec () ; LogMessage ( L"Leaving CResourceManager :: ForcibleCleanUp" ) ; }
CResource* CResourceManager :: GetResource ( GUID ResourceId, PVOID pData ) { std::list < CResourceList* >::iterator pInstanceList ; for ( pInstanceList = m_Resources.begin () ; pInstanceList != m_Resources.end () ; pInstanceList++ ) { if ( IsEqualGUID ( (*pInstanceList)->guidResourceId, ResourceId ) ) { return (*pInstanceList)->GetResource ( pData ) ; } } return NULL ; }
ULONG CResourceManager :: ReleaseResource ( GUID ResourceId, CResource* pResource ) { std::list < CResourceList* >::iterator pInstanceList ; for ( pInstanceList = m_Resources.begin () ; pInstanceList != m_Resources.end () ; pInstanceList++ ) { if ( IsEqualGUID ( (*pInstanceList)->guidResourceId, ResourceId ) ) { return (*pInstanceList)->ReleaseResource ( pResource ) ; } } return ULONG ( -1 ) ; }
BOOL CResourceManager :: AddInstanceCreator ( GUID ResourceId, PFN_RESOURCE_INSTANCE_CREATOR pfnResourceInstanceCreator ) { CAutoLock cs ( m_csResourceManager ) ;
//create a node & add it
CResourceList *stResourceInstances = new CResourceList ; if ( stResourceInstances == NULL ) { throw CHeap_Exception( CHeap_Exception::E_ALLOCATION_ERROR ) ; } stResourceInstances->guidResourceId = ResourceId ; stResourceInstances->m_pfnInstanceCreator = pfnResourceInstanceCreator ; m_Resources.push_back ( stResourceInstances ) ;
return TRUE ; }
CResourceList :: CResourceList () { m_bShutDown = FALSE ; }
CResourceList :: ~CResourceList () { m_bShutDown = TRUE ; ShutDown () ; }
CResource* CResourceList :: GetResource ( LPVOID pData ) { CResource* pTmpInstance = NULL ; tagInstances::iterator ppInstance ; BOOL bRet ;
//check if we're shutting down
if ( m_bShutDown ) { return NULL ; }
//Lock the list
CResourceListAutoLock cs ( this ) ;
//check if we're shutting down
if ( m_bShutDown ) { return NULL ; }
try { //go thru all the instances of this resource & hand out the first valid one
for ( ppInstance = m_Instances.begin(); ppInstance != m_Instances.end (); ppInstance++ ) { //Check out if we've cached a similar instance
if ( ( *ppInstance )->IsOneOfMe ( pData ) ) { //try to acquire the resource...this will up the refcount.
bRet = ( *ppInstance )->Acquire () ;
if ( bRet ) { pTmpInstance = *ppInstance ; break ; //got the instance so break
} } }
//if we haven't got a cached instance to hand out, create a new instance
if ( !pTmpInstance ) { //this will create a new instance but the ref-count is still zero
pTmpInstance = m_pfnInstanceCreator ( pData ) ;
//Try to acquire the instance for the client ..which will up the ref-count
if ( pTmpInstance ) { if ( pTmpInstance->IsValid () ) { pTmpInstance->SetParent ( this ) ; bRet = pTmpInstance->Acquire () ;
//if the acquire succeeded on the instance, add it to our list of cached instances
if ( bRet ) { m_Instances.insert ( m_Instances.begin (), pTmpInstance ) ; } else { delete pTmpInstance ; pTmpInstance = NULL ; } } else { // set creation error as they can look for it
::SetLastError ( pTmpInstance->GetCreationError () );
delete pTmpInstance ; pTmpInstance = NULL ; } } } } catch ( ... ) { if ( pTmpInstance ) { delete pTmpInstance ; pTmpInstance = NULL ; }
throw ; }
return pTmpInstance ; }
ULONG CResourceList :: ReleaseResource ( CResource* pResource ) { CResource* pTmpInstance = NULL ; tagInstances::iterator ppInstance ; LONG lCount = -1 ;
//check if we're shutting down
if ( m_bShutDown ) { return NULL ; }
//Lock the list
CResourceListAutoLock cs ( this ) ;
//check if we're shutting down
if ( m_bShutDown ) { return lCount ; }
//Go thru the list & release the resource
for ( ppInstance = m_Instances.begin(); ppInstance != m_Instances.end (); ppInstance++ ) { if ( *ppInstance == pResource ) { lCount = pResource->Release () ; break ; } } return lCount ; }
//This function will be called by the CResource to remove it's entry from the list of instances. The resource should have a
//lock on the list before it attempts to do this
void CResourceList :: RemoveFromList ( CResource* pResource ) { tagInstances::iterator ppInstance ;
//Go thru the list & remove the link to the resource
for ( ppInstance = m_Instances.begin(); ppInstance != m_Instances.end (); ppInstance++ ) { if ( *ppInstance == pResource ) { m_Instances.erase ( ppInstance ) ; break ; } } }
void CResourceList :: ShutDown () { CResourceListAutoLock cs ( this ) ;
LPOLESTR t_pOleStr = NULL ; CHString t_chsListGuid ; if ( StringFromCLSID ( guidResourceId , &t_pOleStr ) == S_OK ) { t_chsListGuid = t_pOleStr ; CoTaskMemFree ( t_pOleStr ) ; }
tagInstances::iterator ppInstance ;
//Go thru the list & remove the link to the resource
while ( !m_Instances.empty () ) { #if (defined DEBUG || defined _DEBUG)
// Note that this COULD be because there is a timer rule, and the time hasn't expired
// before the DllCanUnloadNow function is called by com (that's who calls this function).
LogErrorMessage3 ( L"%s%s" , L"Resource not released before shutdown = " , t_chsListGuid ) ; #endif
m_Instances.pop_front() ; } }
CResource :: CResource () : m_bValid ( TRUE ), m_dwCreationError ( ERROR_SUCCESS ) { m_pRules = NULL ; m_lRef = 0 ; m_pResources = NULL ; }
CResource :: ~CResource () { }
//This function increments ref-count of the object & calls into the virtual overridables OnAcquire or OnInitialAcquire
//The derived class should override these functions if it wants to & decrement the ref-count if it wants the Acquire
//operation to fail
BOOL CResource::Acquire () { BOOL bRet ; ++m_lRef ; if ( m_lRef == 1 ) { bRet = OnInitialAcquire () ; } else { bRet = OnAcquire () ; }
if ( m_lRef == 0 ) { m_pResources->RemoveFromList ( this ) ; if ( m_pRules ) { //since we're going away, we detach ourselves from the rule so that the rules don't call into us
m_pRules->Detach () ; m_pRules->Release () ; m_pRules = NULL ; } delete this ;
//we do not want to use instance which got deleted
bRet = FALSE; }
return bRet ; }
ULONG CResource::Release () { BOOL bRet ; ULONG lCount = 0 ; --m_lRef ; if ( m_lRef == 0 ) { bRet = OnFinalRelease () ; } else { bRet = OnRelease () ; }
if ( bRet ) { if ( m_lRef == 0 ) { m_pResources->RemoveFromList ( this ) ; if ( m_pRules ) { //since we're going away, we detach ourselves from the rule so that the rules don't call into us
m_pRules->Detach () ; m_pRules->Release () ; m_pRules = NULL ; } delete this ; return lCount ; } }
return m_lRef ; } /*
void CResource :: RuleEvaluated ( const CRule *a_RuleEvaluated ) { if ( m_pRules ) { return m_pRules->CheckRule () ; } else { return FALSE ; } } */
|