Stacks nsFactoryEntry's so that we can support overloading factories a bit better. r=darin, a=blizzard, b=204870

This commit is contained in:
dougt%meer.net 2003-05-13 22:50:03 +00:00
parent f92bb7c89e
commit 3c693caabd
2 changed files with 111 additions and 101 deletions

View File

@ -267,7 +267,7 @@ factory_GetKey(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
{
nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
return &entry->mFactoryEntry->cid;
return &entry->mFactoryEntry->mCid;
}
PR_STATIC_CALLBACK(PLDHashNumber)
@ -286,7 +286,7 @@ factory_MatchEntry(PLDHashTable *aTable, const PLDHashEntryHdr *aHdr,
NS_STATIC_CAST(const nsFactoryTableEntry*, aHdr);
const nsCID *cidp = NS_REINTERPRET_CAST(const nsCID*, aKey);
return (entry->mFactoryEntry->cid).Equals(*cidp);
return (entry->mFactoryEntry->mCid).Equals(*cidp);
}
PR_STATIC_CALLBACK(void)
@ -335,8 +335,8 @@ contractID_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
{
nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
if (entry->mFactoryEntry != kNonExistentContractID &&
entry->mFactoryEntry->typeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY &&
entry->mFactoryEntry->cid.Equals(kEmptyCID)) {
entry->mFactoryEntry->mTypeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY &&
entry->mFactoryEntry->mCid.Equals(kEmptyCID)) {
// this object is owned by the hash.
// nsFactoryEntry is arena allocated. So we dont delete it.
// We call the destructor by hand.
@ -367,18 +367,21 @@ MOZ_DECL_CTOR_COUNTER(nsFactoryEntry)
nsFactoryEntry::nsFactoryEntry(const nsCID &aClass,
const char *aLocation,
PRUint32 locationlen,
int aType)
: cid(aClass), typeIndex(aType)
int aType,
class nsFactoryEntry* parent)
: mCid(aClass), mTypeIndex(aType), mParent(parent)
{
// Arena allocate the location string
location = ArenaStrndup(aLocation, locationlen, &nsComponentManagerImpl::gComponentManager->mArena);
mLocation = ArenaStrndup(aLocation, locationlen, &nsComponentManagerImpl::gComponentManager->mArena);
}
nsFactoryEntry::nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory)
: cid(aClass), typeIndex(NS_COMPONENT_TYPE_FACTORY_ONLY)
nsFactoryEntry::nsFactoryEntry(const nsCID &aClass,
nsIFactory *aFactory,
class nsFactoryEntry* parent)
: mCid(aClass), mTypeIndex(NS_COMPONENT_TYPE_FACTORY_ONLY), mParent(parent)
{
factory = aFactory;
location = nsnull;
mFactory = aFactory;
mLocation = nsnull;
}
// nsFactoryEntry is usually arena allocated including the strings it
@ -386,42 +389,33 @@ nsFactoryEntry::nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory)
nsFactoryEntry::~nsFactoryEntry(void)
{
// Release the reference to the factory
factory = nsnull;
mFactory = nsnull;
// Release any service reference
mServiceObject = nsnull;
// nsFactoryEntry is arena allocated. So we dont delete it.
// We call the destructor by hand.
if (mParent)
mParent->~nsFactoryEntry();
}
nsresult
nsFactoryEntry::ReInit(const nsCID &aClass, const char *aLocation, int aType)
{
NS_ENSURE_TRUE(typeIndex != NS_COMPONENT_TYPE_FACTORY_ONLY, NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE(mTypeIndex != NS_COMPONENT_TYPE_FACTORY_ONLY, NS_ERROR_INVALID_ARG);
// cid has to match
// SERVICE_ONLY entries can be promoted to an entry of another type
NS_ENSURE_TRUE((typeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY || cid.Equals(aClass)),
NS_ENSURE_TRUE((mTypeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY || mCid.Equals(aClass)),
NS_ERROR_INVALID_ARG);
// Arena allocate the location string
location = ArenaStrdup(aLocation, &nsComponentManagerImpl::gComponentManager->mArena);
mLocation = ArenaStrdup(aLocation, &nsComponentManagerImpl::gComponentManager->mArena);
typeIndex = aType;
mTypeIndex = aType;
return NS_OK;
}
nsresult
nsFactoryEntry::ReInit(const nsCID &aClass, nsIFactory *aFactory)
{
// cids has to match
// SERVICE_ONLY entries can be promoted to an entry of another type
NS_ENSURE_TRUE((typeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY || cid.Equals(aClass)),
NS_ERROR_INVALID_ARG);
// We are going to let native component be overridden by a factory.
factory = aFactory;
typeIndex = NS_COMPONENT_TYPE_FACTORY_ONLY;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// Hashtable Enumeration
////////////////////////////////////////////////////////////////////////////////
@ -650,7 +644,7 @@ ConvertFactoryEntryToCID(PLDHashTable *table,
if (entry) {
nsFactoryEntry *fe = entry->mFactoryEntry;
wrapper->SetData(&fe->cid);
wrapper->SetData(&fe->mCid);
*retval = wrapper;
NS_ADDREF(*retval);
return NS_OK;
@ -1215,7 +1209,7 @@ nsComponentManagerImpl::ReadPersistentRegistry()
//need to find the location for this cid.
nsFactoryEntry *cidEntry = GetFactoryEntry(aClass);
if (!cidEntry || cidEntry->typeIndex < 0)
if (!cidEntry || cidEntry->mTypeIndex < 0)
continue; //what should we really do?
nsContractIDTableEntry* contractIDTableEntry =
@ -1280,13 +1274,18 @@ ContractIDWriter(PLDHashTable *table,
{
char *contractID = ((nsContractIDTableEntry*)hdr)->mContractID;
nsFactoryEntry *factoryEntry = ((nsContractIDTableEntry*)hdr)->mFactoryEntry;
if (factoryEntry == kNonExistentContractID || factoryEntry->typeIndex < 0)
// for now, we only save out the top most parent.
while (factoryEntry != kNonExistentContractID && factoryEntry->mParent)
factoryEntry = factoryEntry->mParent;
if (factoryEntry == kNonExistentContractID || factoryEntry->mTypeIndex < 0)
return PL_DHASH_NEXT;
PRFileDesc* fd = ((PersistentWriterArgs*)arg)->mFD;
char cidString[UID_STRING_LENGTH];
GetIDString(factoryEntry->cid, cidString);
GetIDString(factoryEntry->mCid, cidString);
PR_fprintf(fd, "%s,%s\n", contractID, cidString); // what if this fails?
return PL_DHASH_NEXT;
}
@ -1301,16 +1300,20 @@ ClassIDWriter(PLDHashTable *table,
PRFileDesc* fd = ((PersistentWriterArgs*)arg)->mFD;
nsLoaderdata *loaderData = ((PersistentWriterArgs*)arg)->mLoaderData;
if (factoryEntry->typeIndex < 0)
return PL_DHASH_NEXT;
// for now, we only save out the top most parent.
while (factoryEntry->mParent)
factoryEntry = factoryEntry->mParent;
if (factoryEntry->mTypeIndex < 0) {
return PL_DHASH_NEXT;
}
char cidString[UID_STRING_LENGTH];
GetIDString(factoryEntry->cid, cidString);
GetIDString(factoryEntry->mCid, cidString);
char *contractID = nsnull, *className = nsnull;
nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(factoryEntry->factory);
nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(factoryEntry->mFactory);
if (classInfo)
{
classInfo->GetContractID(&contractID);
@ -1318,10 +1321,10 @@ ClassIDWriter(PLDHashTable *table,
}
const char * loaderName = nsnull;
if (factoryEntry->typeIndex)
loaderName = loaderData[factoryEntry->typeIndex].type;
if (factoryEntry->mTypeIndex)
loaderName = loaderData[factoryEntry->mTypeIndex].type;
char* location = factoryEntry->location;
char* location = factoryEntry->mLocation;
// cid,contract_id,type,class_name,inproc_server
PR_fprintf(fd,
@ -1605,7 +1608,7 @@ nsComponentManagerImpl::LoadFactory(nsFactoryEntry *aEntry,
if (NS_FAILED(rv)) {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("nsComponentManager: FAILED to load factory from %s (%s)\n",
(const char *)aEntry->location, mLoaderData[aEntry->typeIndex].type));
(const char *)aEntry->mLocation, mLoaderData[aEntry->mTypeIndex].type));
return rv;
}
@ -1725,6 +1728,7 @@ nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID,
nsCOMPtr<nsIFactory> factory;
#ifdef PR_LOGGING
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
{
char *buf = aClass.ToString();
@ -1732,6 +1736,7 @@ nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID,
if (buf)
PR_Free(buf);
}
#endif
PR_ASSERT(aResult != nsnull);
@ -1756,10 +1761,12 @@ nsComponentManagerImpl::GetClassObjectByContractID(const char *contractID,
nsCOMPtr<nsIFactory> factory;
#ifdef PR_LOGGING
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
{
PR_LogPrint("nsComponentManager: GetClassObject(%s)", contractID);
}
#endif
PR_ASSERT(aResult != nsnull);
@ -1795,10 +1802,10 @@ nsComponentManagerImpl::ContractIDToClassID(const char *aContractID, nsCID *aCla
nsFactoryEntry *fe = GetFactoryEntry(aContractID, strlen(aContractID));
if (fe && fe != kNonExistentContractID) {
*aClass = fe->cid;
*aClass = fe->mCid;
rv = NS_OK;
}
#ifdef PR_LOGGING
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS)) {
char *buf = 0;
if (NS_SUCCEEDED(rv))
@ -1809,7 +1816,7 @@ nsComponentManagerImpl::ContractIDToClassID(const char *aContractID, nsCID *aCla
if (buf)
PR_Free(buf);
}
#endif
return rv;
}
@ -1829,7 +1836,7 @@ nsComponentManagerImpl::CLSIDToContractID(const nsCID &aClass,
NS_WARNING("Need to implement CLSIDToContractID");
nsresult rv = NS_ERROR_FACTORY_NOT_REGISTERED;
#ifdef PR_LOGGING
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
{
char *buf = aClass.ToString();
@ -1839,7 +1846,7 @@ nsComponentManagerImpl::CLSIDToContractID(const nsCID &aClass,
if (buf)
PR_Free(buf);
}
#endif
return rv;
}
@ -1930,7 +1937,7 @@ nsComponentManagerImpl::CreateInstance(const nsCID &aClass,
rv = NS_ERROR_FACTORY_NOT_REGISTERED;
}
#ifdef PR_LOGGING
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
{
char *buf = aClass.ToString();
@ -1940,6 +1947,7 @@ nsComponentManagerImpl::CreateInstance(const nsCID &aClass,
if (buf)
PR_Free(buf);
}
#endif
return rv;
}
@ -2160,7 +2168,7 @@ nsComponentManagerImpl::RegisterService(const nsCID& aClass, nsISupports* aServi
return NS_ERROR_OUT_OF_MEMORY;
entry = new (mem) nsFactoryEntry(aClass, nsnull);
entry->typeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
entry->mTypeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
nsFactoryTableEntry* factoryTableEntry =
NS_STATIC_CAST(nsFactoryTableEntry*,
PL_DHashTableOperate(&mFactories, &aClass,
@ -2224,7 +2232,7 @@ nsComponentManagerImpl::RegisterService(const char* aContractID, nsISupports* aS
return NS_ERROR_OUT_OF_MEMORY;
entry = new (mem) nsFactoryEntry(kEmptyCID, nsnull);
entry->typeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
entry->mTypeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
nsContractIDTableEntry* contractIDTableEntry =
NS_STATIC_CAST(nsContractIDTableEntry*,
@ -2403,7 +2411,7 @@ nsComponentManagerImpl::GetServiceByContractID(const char* aContractID,
}
#ifdef XPCOM_CHECK_PENDING_CIDS
rv = AddPendingCID(entry->cid);
rv = AddPendingCID(entry->mCid);
if (NS_FAILED(rv))
return rv;
#endif
@ -2418,7 +2426,7 @@ nsComponentManagerImpl::GetServiceByContractID(const char* aContractID,
mon.Enter();
#ifdef XPCOM_CHECK_PENDING_CIDS
RemovePendingCID(entry->cid);
RemovePendingCID(entry->mCid);
#endif
if (NS_FAILED(rv))
@ -2643,13 +2651,8 @@ nsComponentManagerImpl::RegisterFactory(const nsCID &aClass,
nsIFactory *aFactory,
PRBool aReplace)
{
nsFactoryEntry *entry = nsnull;
nsIDKey key(aClass);
nsAutoMonitor mon(mMon);
entry = GetFactoryEntry(aClass, key);
#ifdef PR_LOGGING
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
{
char *buf = aClass.ToString();
@ -2659,35 +2662,40 @@ nsComponentManagerImpl::RegisterFactory(const nsCID &aClass,
if (buf)
PR_Free(buf);
}
#endif
nsFactoryEntry *entry = nsnull;
nsFactoryTableEntry* factoryTableEntry = NS_STATIC_CAST(nsFactoryTableEntry*,
PL_DHashTableOperate(&mFactories,
&aClass,
PL_DHASH_ADD));
if (!factoryTableEntry)
return NS_ERROR_OUT_OF_MEMORY;
if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
entry = factoryTableEntry->mFactoryEntry;
}
if (entry && !aReplace) {
if (entry && !aReplace)
{
// Already registered
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tFactory already registered."));
return NS_ERROR_FACTORY_EXISTS;
}
if (entry) {
entry->ReInit(aClass, aFactory);
}
else {
void *mem;
PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
if (!mem)
return NS_ERROR_OUT_OF_MEMORY;
entry = new (mem) nsFactoryEntry(aClass, aFactory);
void *mem;
PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
if (!mem)
return NS_ERROR_OUT_OF_MEMORY;
nsFactoryTableEntry* factoryTableEntry =
NS_STATIC_CAST(nsFactoryTableEntry*,
PL_DHashTableOperate(&mFactories, &aClass,
PL_DHASH_ADD));
entry = new (mem) nsFactoryEntry(aClass, aFactory, entry);
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
if (!factoryTableEntry)
return NS_ERROR_OUT_OF_MEMORY;
factoryTableEntry->mFactoryEntry = entry;
}
factoryTableEntry->mFactoryEntry = entry;
// Update the ContractID->CLSID Map
if (aContractID) {
@ -2808,7 +2816,7 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
// Normalize proid and classname
const char *contractID = (aContractID && *aContractID) ? aContractID : nsnull;
const char *className = (aClassName && *aClassName) ? aClassName : nsnull;
#ifdef PR_LOGGING
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
{
char *buf = aClass.ToString();
@ -2820,7 +2828,7 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
if (buf)
PR_Free(buf);
}
#endif
if (entry && !aReplace) {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tFactory already registered."));
@ -2987,9 +2995,9 @@ DeleteFoundCIDs(PLDHashTable *aTable,
UnregisterConditions* data = (UnregisterConditions*)aData;
nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
if (data->cid->Equals(factoryEntry->cid) &&
((data->regName && !PL_strcasecmp(factoryEntry->location, data->regName)) ||
(data->factory && data->factory == factoryEntry->factory.get())))
if (data->cid->Equals(factoryEntry->mCid) &&
((data->regName && !PL_strcasecmp(factoryEntry->mLocation, data->regName)) ||
(data->factory && data->factory == factoryEntry->mFactory.get())))
return PL_DHASH_REMOVE;
return PL_DHASH_NEXT;
@ -3020,6 +3028,7 @@ nsresult
nsComponentManagerImpl::UnregisterFactory(const nsCID &aClass,
nsIFactory *aFactory)
{
#ifdef PR_LOGGING
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
{
char *buf = aClass.ToString();
@ -3028,7 +3037,7 @@ nsComponentManagerImpl::UnregisterFactory(const nsCID &aClass,
if (buf)
PR_Free(buf);
}
#endif
nsFactoryEntry *old;
// first delete all contract id entries that are registered with this cid.
@ -3039,7 +3048,7 @@ nsComponentManagerImpl::UnregisterFactory(const nsCID &aClass,
nsresult rv = NS_ERROR_FACTORY_NOT_REGISTERED;
old = GetFactoryEntry(aClass, key);
if (old && (old->factory.get() == aFactory))
if (old && (old->mFactory.get() == aFactory))
{
nsAutoMonitor mon(mMon);
PL_DHashTableOperate(&mFactories, &aClass, PL_DHASH_REMOVE);
@ -3056,6 +3065,7 @@ nsresult
nsComponentManagerImpl::UnregisterComponent(const nsCID &aClass,
const char *registryName)
{
#ifdef PR_LOGGING
if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_ALWAYS))
{
char *buf = aClass.ToString();
@ -3064,6 +3074,7 @@ nsComponentManagerImpl::UnregisterComponent(const nsCID &aClass,
if (buf)
PR_Free(buf);
}
#endif
NS_ENSURE_ARG_POINTER(registryName);
nsFactoryEntry *old;
@ -3074,7 +3085,7 @@ nsComponentManagerImpl::UnregisterComponent(const nsCID &aClass,
// next check to see if there is a CID registered
nsIDKey key(aClass);
old = GetFactoryEntry(aClass, key);
if (old && old->location && !PL_strcasecmp(old->location, registryName))
if (old && old->mLocation && !PL_strcasecmp(old->mLocation, registryName))
{
nsAutoMonitor mon(mMon);
PL_DHashTableOperate(&mFactories, &aClass, PL_DHASH_REMOVE);
@ -3206,7 +3217,7 @@ nsComponentManagerImpl::AutoRegisterImpl(PRInt32 when,
if (!mCategoryManager) {
NS_WARNING("mCategoryManager is null");
return NS_ERROR_UNEXPECTED;
}
}
nsCOMPtr<nsISimpleEnumerator> loaderEnum;
rv = mCategoryManager->EnumerateCategory("component-loader",

View File

@ -300,43 +300,42 @@ protected:
class nsFactoryEntry {
public:
nsFactoryEntry(const nsCID &aClass,
const char *location, PRUint32 locationlen, int aType);
nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory);
const char *location, PRUint32 locationlen, int aType, class nsFactoryEntry* parent = nsnull);
nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory, class nsFactoryEntry* parent = nsnull);
~nsFactoryEntry();
nsresult ReInit(const nsCID &aClass, const char *location, int aType);
nsresult ReInit(const nsCID &aClass, nsIFactory *aFactory);
nsresult GetFactory(nsIFactory **aFactory,
nsComponentManagerImpl * mgr) {
if (factory) {
*aFactory = factory.get();
if (mFactory) {
*aFactory = mFactory.get();
NS_ADDREF(*aFactory);
return NS_OK;
}
if (typeIndex < 0)
if (mTypeIndex < 0)
return NS_ERROR_FAILURE;
nsresult rv;
nsCOMPtr<nsIComponentLoader> loader;
rv = mgr->GetLoaderForType(typeIndex, getter_AddRefs(loader));
rv = mgr->GetLoaderForType(mTypeIndex, getter_AddRefs(loader));
if(NS_FAILED(rv))
return rv;
rv = loader->GetFactory(cid, location, mgr->mLoaderData[typeIndex].type, aFactory);
rv = loader->GetFactory(mCid, mLocation, mgr->mLoaderData[mTypeIndex].type, aFactory);
if (NS_SUCCEEDED(rv))
factory = do_QueryInterface(*aFactory);
mFactory = do_QueryInterface(*aFactory);
return rv;
}
nsCID cid;
nsCOMPtr<nsIFactory> factory;
nsCID mCid;
nsCOMPtr<nsIFactory> mFactory;
// This is an index into the mLoaderData array that holds the type string and the loader
int typeIndex;
int mTypeIndex;
nsCOMPtr<nsISupports> mServiceObject;
char* location;
char* mLocation;
class nsFactoryEntry* mParent;
};
////////////////////////////////////////////////////////////////////////////////