NOT YET PART OF SEAMONKEY BUILD. added locking

This commit is contained in:
jband%netscape.com 2000-04-18 21:33:46 +00:00
parent d26b29c168
commit 89115d7adc
3 changed files with 120 additions and 72 deletions

View File

@ -82,8 +82,16 @@ xptiInterfaceInfo::~xptiInterfaceInfo()
delete mInterface;
}
PRBool
xptiInterfaceInfo::Resolve(xptiWorkingSet* aWorkingSet)
xptiInterfaceInfo::Resolve(xptiWorkingSet* aWorkingSet /* = nsnull */)
{
nsAutoLock lock(xptiInterfaceInfoManager::GetResolveLock());
return ResolveLocked(aWorkingSet);
}
PRBool
xptiInterfaceInfo::ResolveLocked(xptiWorkingSet* aWorkingSet /* = nsnull */)
{
int resolvedState = GetResolveState();
@ -93,7 +101,7 @@ xptiInterfaceInfo::Resolve(xptiWorkingSet* aWorkingSet)
return PR_FALSE;
xptiInterfaceInfoManager* mgr =
xptiInterfaceInfoManager::GetInterfaceInfoManager();
xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
if(!mgr)
return PR_FALSE;
@ -109,17 +117,16 @@ xptiInterfaceInfo::Resolve(xptiWorkingSet* aWorkingSet)
// Make a copy of mTypelib because the underlying memory will change!
xptiTypelib typelib = mTypelib;
// We expect our PartiallyResolve() to get called before this returns.
// We expect our PartiallyResolveLocked() to get called before
// this returns.
if(!mgr->LoadFile(typelib, aWorkingSet))
{
NS_RELEASE(mgr);
SetResolvedState(RESOLVE_FAILED);
return PR_FALSE;
}
// The state was changed by LoadFile to PARTIALLY_RESOLVED, so this
// ...falls through...
}
NS_IF_RELEASE(mgr);
NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!");
@ -134,7 +141,7 @@ xptiInterfaceInfo::Resolve(xptiWorkingSet* aWorkingSet)
aWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
GetInfoAtNoAddRef(parent_index - 1);
if(!parent || !parent->EnsureResolved())
if(!parent || !parent->EnsureResolvedLocked())
{
xptiTypelib aTypelib = mInterface->mTypelib;
delete mInterface;
@ -160,9 +167,10 @@ xptiInterfaceInfo::Resolve(xptiWorkingSet* aWorkingSet)
return PR_TRUE;
}
// This *only* gets called by xptiInterfaceInfoManager::LoadFile (while locked).
PRBool
xptiInterfaceInfo::PartiallyResolve(XPTInterfaceDescriptor* aDescriptor,
xptiWorkingSet* aWorkingSet)
xptiInterfaceInfo::PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
xptiWorkingSet* aWorkingSet)
{
NS_ASSERTION(GetResolveState() == NOT_RESOLVED, "bad state");
@ -213,16 +221,9 @@ xptiInterfaceInfo::IsScriptable(PRBool* result)
{
NS_ASSERTION(result, "bad bad caller!");
/*
if(!EnsureResolved())
{
EnsureResolved();
return NS_ERROR_UNEXPECTED;
}
*/
// It is not necessary to Resolve because this info is read from manifest.
NS_ASSERTION(ScriptableFlagIsValid(), "scriptable flag out of sync!");
*result = GetScriptableFlag();
return NS_OK;
}

View File

@ -30,35 +30,36 @@ static xptiInterfaceInfoManager* gInterfaceInfoManager = nsnull;
// static
xptiInterfaceInfoManager*
xptiInterfaceInfoManager::GetInterfaceInfoManager()
xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef()
{
if(!gInterfaceInfoManager)
{
gInterfaceInfoManager = new xptiInterfaceInfoManager();
if(gInterfaceInfoManager)
NS_ADDREF(gInterfaceInfoManager);
if(!gInterfaceInfoManager->mWorkingSet.IsValid())
NS_RELEASE(gInterfaceInfoManager);
PRBool mustAutoReg =
!xptiManifest::Read(gInterfaceInfoManager,
&gInterfaceInfoManager->mWorkingSet);
#ifdef DEBUG
if(!gInterfaceInfoManager->IsValid())
{
// This sets what will be returned by GetOpenLogFile().
xptiAutoLog autoLog(gInterfaceInfoManager,
gInterfaceInfoManager->mAutoRegLogFile, PR_TRUE);
LOG_AUTOREG(("debug build forced autoreg after %s load of manifest\n", mustAutoReg ? "FAILED" : "successful"));
mustAutoReg = PR_TRUE;
NS_RELEASE(gInterfaceInfoManager);
}
else
{
PRBool mustAutoReg =
!xptiManifest::Read(gInterfaceInfoManager,
&gInterfaceInfoManager->mWorkingSet);
#ifdef DEBUG
{
// This sets what will be returned by GetOpenLogFile().
xptiAutoLog autoLog(gInterfaceInfoManager,
gInterfaceInfoManager->mAutoRegLogFile, PR_TRUE);
LOG_AUTOREG(("debug build forced autoreg after %s load of manifest\n", mustAutoReg ? "FAILED" : "successful"));
mustAutoReg = PR_TRUE;
}
#endif // DEBUG
if(mustAutoReg)
gInterfaceInfoManager->AutoRegisterInterfaces();
if(mustAutoReg)
gInterfaceInfoManager->AutoRegisterInterfaces();
}
}
if(gInterfaceInfoManager)
NS_ADDREF(gInterfaceInfoManager);
return gInterfaceInfoManager;
}
@ -71,9 +72,20 @@ xptiInterfaceInfoManager::FreeInterfaceInfoManager()
NS_IF_RELEASE(gInterfaceInfoManager);
}
PRBool
xptiInterfaceInfoManager::IsValid()
{
return mWorkingSet.IsValid() &&
mResolveLock &&
mAutoRegLock;
}
xptiInterfaceInfoManager::xptiInterfaceInfoManager()
: mWorkingSet(),
mOpenLogFile(nsnull)
mOpenLogFile(nsnull),
mResolveLock(PR_NewLock()),
mAutoRegLock(PR_NewLock())
{
NS_INIT_ISUPPORTS();
@ -361,7 +373,7 @@ xptiInterfaceInfoManager::LoadFile(const xptiTypelib& aTypelibRecord,
XPTInterfaceDescriptor* descriptor = iface->interface_descriptor;
if(descriptor && aTypelibRecord.Equals(info->GetTypelibRecord()))
info->PartiallyResolve(descriptor, aWorkingSet);
info->PartiallyResolveLocked(descriptor, aWorkingSet);
}
return PR_TRUE;
}
@ -1059,27 +1071,32 @@ PRBool
xptiInterfaceInfoManager::MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
xptiWorkingSet* aSrcWorkingSet)
{
// Combine file lists.
PRUint32 i;
// Combine file lists.
PRUint32 originalFileCount = aDestWorkingSet->GetFileCount();
PRUint32 additionalFileCount = aSrcWorkingSet->GetFileCount();
// Create a new array big enough to hold both lists and copy existing files
if(!aDestWorkingSet->ExtendFileArray(originalFileCount +
additionalFileCount))
return PR_FALSE;
// Now we are where we started, but we know we have enough space.
// Prepare offset array for later fixups.
// NOTE: Storing with dest, but alloc'ing from src. This is intentional.
aDestWorkingSet->mFileMergeOffsetMap = (PRUint32*)
XPT_CALLOC(aSrcWorkingSet->GetStructArena(),
additionalFileCount * sizeof(PRUint32));
if(!aDestWorkingSet->mFileMergeOffsetMap)
return PR_FALSE;
if(additionalFileCount)
{
if(!aDestWorkingSet->ExtendFileArray(originalFileCount +
additionalFileCount))
return PR_FALSE;
// Now we are where we started, but we know we have enough space.
// Prepare offset array for later fixups.
// NOTE: Storing with dest, but alloc'ing from src. This is intentional.
aDestWorkingSet->mFileMergeOffsetMap = (PRUint32*)
XPT_CALLOC(aSrcWorkingSet->GetStructArena(),
additionalFileCount * sizeof(PRUint32));
if(!aDestWorkingSet->mFileMergeOffsetMap)
return PR_FALSE;
}
for(i = 0; i < additionalFileCount; ++i)
{
@ -1117,20 +1134,22 @@ xptiInterfaceInfoManager::MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
// Create a new array big enough to hold both lists and copy existing ZipItems
if(!aDestWorkingSet->ExtendZipItemArray(originalZipItemCount +
additionalZipItemCount))
return PR_FALSE;
// Now we are where we started, but we know we have enough space.
// Prepare offset array for later fixups.
// NOTE: Storing with dest, but alloc'ing from src. This is intentional.
aDestWorkingSet->mZipItemMergeOffsetMap = (PRUint32*)
XPT_CALLOC(aSrcWorkingSet->GetStructArena(),
additionalZipItemCount * sizeof(PRUint32));
if(!aDestWorkingSet->mZipItemMergeOffsetMap)
return PR_FALSE;
if(additionalZipItemCount)
{
if(!aDestWorkingSet->ExtendZipItemArray(originalZipItemCount +
additionalZipItemCount))
return PR_FALSE;
// Now we are where we started, but we know we have enough space.
// Prepare offset array for later fixups.
// NOTE: Storing with dest, but alloc'ing from src. This is intentional.
aDestWorkingSet->mZipItemMergeOffsetMap = (PRUint32*)
XPT_CALLOC(aSrcWorkingSet->GetStructArena(),
additionalZipItemCount * sizeof(PRUint32));
if(!aDestWorkingSet->mZipItemMergeOffsetMap)
return PR_FALSE;
}
for(i = 0; i < additionalZipItemCount; ++i)
{
@ -1439,6 +1458,8 @@ NS_IMETHODIMP xptiInterfaceInfoManager::AutoRegisterInterfaces()
AutoRegMode mode;
PRBool ok;
nsAutoLock lock(xptiInterfaceInfoManager::GetAutoRegLock());
if(!workingSet.IsValid())
return NS_ERROR_UNEXPECTED;
@ -1515,7 +1536,10 @@ NS_IMETHODIMP xptiInterfaceInfoManager::AutoRegisterInterfaces()
XPTI_PUBLIC_API(nsIInterfaceInfoManager*)
XPTI_GetInterfaceInfoManager()
{
return xptiInterfaceInfoManager::GetInterfaceInfoManager();
nsIInterfaceInfoManager* iim =
xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
NS_IF_ADDREF(iim);
return iim;
}
XPTI_PUBLIC_API(void)

View File

@ -50,6 +50,8 @@
#include "nsIInputStream.h"
#include "nsIPref.h"
#include "nsAutoLock.h"
#include "plstr.h"
#include "prprf.h"
#include "prio.h"
@ -444,7 +446,7 @@ public:
virtual ~xptiInterfaceInfo();
// We use mName[-1] (cast as a xptiInfoFlags) to hold the two bit state
// below and alos the bit flags that follow. If the states ever grow beyond
// below and also the bit flags that follow. If the states ever grow beyond
// 2 bits then these flags need to be adjusted along with STATE_MASK in
// xptiInfoFlags.
@ -482,8 +484,8 @@ public:
const nsID* GetTheIID() const {return &mIID;}
const char* GetTheName() const {return mName;}
PRBool PartiallyResolve(XPTInterfaceDescriptor* aDescriptor,
xptiWorkingSet* aWorkingSet);
PRBool PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
xptiWorkingSet* aWorkingSet);
void Invalidate()
{
@ -506,10 +508,17 @@ private:
{NS_ASSERTION(IsValid(),"bad state");
GetFlags().SetState(uint8(state));}
PRBool Resolve(xptiWorkingSet* aWorkingSet = nsnull);
PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
{return IsFullyResolved() ? PR_TRUE : Resolve(aWorkingSet);}
PRBool Resolve(xptiWorkingSet* aWorkingSet = nsnull);
// We only call these "*Locked" varients after locking. This is done to
// allow reentrace as files are loaded and various interfaces resolved
// without having to worry about the locked state.
PRBool EnsureResolvedLocked(xptiWorkingSet* aWorkingSet = nsnull)
{return IsFullyResolved() ? PR_TRUE : ResolveLocked(aWorkingSet);}
PRBool ResolveLocked(xptiWorkingSet* aWorkingSet = nsnull);
PRBool ScriptableFlagIsValid() const
{int s = (int) GetResolveState();
@ -644,7 +653,7 @@ class xptiInterfaceInfoManager
public:
virtual ~xptiInterfaceInfoManager();
static xptiInterfaceInfoManager* GetInterfaceInfoManager();
static xptiInterfaceInfoManager* GetInterfaceInfoManagerNoAddRef();
static void FreeInterfaceInfoManager();
xptiWorkingSet* GetWorkingSet() {return &mWorkingSet;}
@ -656,6 +665,16 @@ public:
xptiWorkingSet* aWorkingSet = nsnull);
PRBool GetComponentsDir(nsILocalFile** aDir);
static PRLock* GetResolveLock(xptiInterfaceInfoManager* self = nsnull)
{if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
return nsnull;
return self->mResolveLock;}
static PRLock* GetAutoRegLock(xptiInterfaceInfoManager* self = nsnull)
{if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
return nsnull;
return self->mAutoRegLock;}
static void WriteToLog(const char *fmt, ...);
@ -668,6 +687,8 @@ private:
FULL_VALIDATION_REQUIRED
};
PRBool IsValid();
PRBool BuildFileList(nsISupportsArray** aFileList);
nsILocalFile** BuildOrderedFileArray(nsISupportsArray* aFileList,
@ -703,6 +724,8 @@ private:
nsCOMPtr<nsILocalFile> mStatsLogFile;
nsCOMPtr<nsILocalFile> mAutoRegLogFile;
PRFileDesc* mOpenLogFile;
PRLock* mResolveLock;
PRLock* mAutoRegLock;
};
#endif /* xptiprivate_h___ */