зеркало из https://github.com/mozilla/pjs.git
NOT YET PART OF SEAMONKEY BUILD. added locking
This commit is contained in:
Родитель
e1cdbeacdf
Коммит
e6a64cb2a6
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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___ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче