author | Ed Morley <bmo@edmorley.co.uk> |
Wed, 11 Jan 2012 17:28:35 +0000 | |
changeset 84298 | 39b93b408124b4362ebcc8aed34a97d46210bc30 |
parent 84297 | dc23947abad9e1246bd9c281b3ce518a38f4e042 (current diff) |
parent 84269 | 40c9f9ff9fd578cd56da91d129374ed361142149 (diff) |
child 84299 | c146569ded26e6118db7ae695e6525d3bbd63dee |
push id | 21839 |
push user | mbrubeck@mozilla.com |
push date | Thu, 12 Jan 2012 16:24:29 +0000 |
treeherder | mozilla-central@fb5bcf9ae739 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 12.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -397,17 +397,17 @@ @BINPATH@/components/nsTelephonyWorker.manifest @BINPATH@/components/nsTelephonyWorker.js @BINPATH@/components/Telephony.manifest @BINPATH@/components/Telephony.js @BINPATH@/components/nsWifiWorker.js @BINPATH@/components/nsWifiWorker.manifest #endif #ifdef XP_MACOSX -@BINPATH@/components/libalerts_s.dylib +@BINPATH@/components/libalerts.dylib #endif #ifdef MOZ_ENABLE_DBUS @BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@ #endif @BINPATH@/components/nsINIProcessor.manifest @BINPATH@/components/nsINIProcessor.js @BINPATH@/components/nsPrompter.manifest @BINPATH@/components/nsPrompter.js
--- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -369,17 +369,17 @@ @BINPATH@/components/Telephony.js @BINPATH@/components/nsWifiWorker.js @BINPATH@/components/nsWifiWorker.manifest #endif @BINPATH@/components/BrowserProfileMigrators.manifest @BINPATH@/components/ChromeProfileMigrator.js @BINPATH@/components/FirefoxProfileMigrator.js #ifdef XP_MACOSX -@BINPATH@/components/libalerts_s.dylib +@BINPATH@/components/libalerts.dylib #endif #ifdef MOZ_ENABLE_DBUS @BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@ #endif @BINPATH@/components/nsINIProcessor.manifest @BINPATH@/components/nsINIProcessor.js @BINPATH@/components/nsPrompter.manifest @BINPATH@/components/nsPrompter.js
--- a/browser/installer/removed-files.in +++ b/browser/installer/removed-files.in @@ -39,16 +39,19 @@ chrome/toolkit.manifest component.reg components/browser.manifest components/components.list components/@DLL_PREFIX@browserdirprovider@DLL_SUFFIX@ components/@DLL_PREFIX@brwsrdir@DLL_SUFFIX@ components/@DLL_PREFIX@myspell@DLL_SUFFIX@ components/@DLL_PREFIX@spellchecker@DLL_SUFFIX@ components/@DLL_PREFIX@spellchk@DLL_SUFFIX@ +#ifdef XP_MACOSX +components/libalerts_s.dylib +#endif components/aboutCertError.js components/aboutPrivateBrowsing.js components/aboutRights.js components/aboutRobots.js components/aboutSessionRestore.js components/autocomplete.xpt components/airbag.xpt components/bookmarks.xpt
--- a/content/events/test/test_bug489671.html +++ b/content/events/test/test_bug489671.html @@ -25,17 +25,17 @@ const Ci = Components.interfaces; const Cr = Components.results; var listener = { observe: function(message) { netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); is(message.QueryInterface(Ci.nsIScriptError).errorMessage, "uncaught exception: Got click"); - nextTest(); + SimpleTest.executeSoon(nextTest); }, QueryInterface: function(iid) { netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); if (iid.equals(Ci.nsIConsoleListener) || iid.equals(Ci.nsISupports)) { return this; }
--- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -385,17 +385,17 @@ @BINPATH@/components/contentSecurityPolicy.js @BINPATH@/components/contentAreaDropListener.manifest @BINPATH@/components/contentAreaDropListener.js @BINPATH@/components/messageWakeupService.js @BINPATH@/components/messageWakeupService.manifest @BINPATH@/components/nsFilePicker.js @BINPATH@/components/nsFilePicker.manifest #ifdef XP_MACOSX -@BINPATH@/components/libalerts_s.dylib +@BINPATH@/components/libalerts.dylib #endif #ifdef MOZ_ENABLE_DBUS @BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@ #endif @BINPATH@/components/nsINIProcessor.manifest @BINPATH@/components/nsINIProcessor.js @BINPATH@/components/nsPrompter.manifest @BINPATH@/components/nsPrompter.js
--- a/mobile/xul/installer/package-manifest.in +++ b/mobile/xul/installer/package-manifest.in @@ -397,17 +397,17 @@ @BINPATH@/components/nsTelephonyWorker.manifest @BINPATH@/components/nsTelephonyWorker.js @BINPATH@/components/Telephony.manifest @BINPATH@/components/Telephony.js @BINPATH@/components/nsWifiWorker.js @BINPATH@/components/nsWifiWorker.manifest #endif #ifdef XP_MACOSX -@BINPATH@/components/libalerts_s.dylib +@BINPATH@/components/libalerts.dylib #endif #ifdef MOZ_ENABLE_DBUS @BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@ #endif @BINPATH@/components/nsINIProcessor.manifest @BINPATH@/components/nsINIProcessor.js @BINPATH@/components/nsPrompter.manifest @BINPATH@/components/nsPrompter.js
--- a/toolkit/components/alerts/mac/Makefile.in +++ b/toolkit/components/alerts/mac/Makefile.in @@ -37,17 +37,17 @@ DEPTH = ../../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = alerts -LIBRARY_NAME = alerts_s +LIBRARY_NAME = alerts IS_COMPONENT = 1 FORCE_SHARED_LIB = 1 CMMSRCS = \ nsAlertsService.mm \ mozGrowlDelegate.mm \ nsAlertsImageLoadListener.mm \ nsNotificationsList.mm \ @@ -65,16 +65,22 @@ LOCAL_INCLUDES += \ EXPORTS = \ nsAlertsService.h \ $(NULL) SHARED_LIBRARY_LIBS = \ growl/$(LIB_PREFIX)growl_s.$(LIB_SUFFIX) \ $(NULL) +ifdef JS_SHARED_LIBRARY +js_ldopts = $(MOZ_JS_LIBS) +else +js_ldopts = $(LIBXUL_LIBS) +endif + EXTRA_DSO_LDOPTS += \ -framework Carbon \ $(XPCOM_GLUE_LDOPTS) \ + $(js_ldopts) \ $(NSPR_LIBS) \ - $(MOZ_JS_LIBS) \ $(NULL) include $(topsrcdir)/config/rules.mk
--- a/xpcom/Makefile.in +++ b/xpcom/Makefile.in @@ -51,34 +51,33 @@ DIRS = \ string \ glue \ base \ ds \ io \ components \ threads \ reflect \ - proxy \ system \ ../chrome \ build \ $(NULL) ifeq ($(OS_ARCH),WINNT) ifdef MOZ_DEBUG DIRS += windbgdlg endif endif ifdef ENABLE_TESTS TOOL_DIRS += \ tests \ sample \ typelib/xpt/tests \ - proxy/tests + $(NULL) # Can't build internal xptcall tests that use symbols which are not exported. #TOOL_DIRS += \ # reflect/xptinfo/tests \ # reflect/xptcall/tests \ # $(NULL) endif
--- a/xpcom/base/nsConsoleService.cpp +++ b/xpcom/base/nsConsoleService.cpp @@ -40,17 +40,16 @@ * Maintains a circular buffer of recent messages, and notifies * listeners when new messages are logged. */ /* Threadsafe. */ #include "nsMemory.h" #include "nsIServiceManager.h" -#include "nsIProxyObjectManager.h" #include "nsCOMArray.h" #include "nsThreadUtils.h" #include "nsConsoleService.h" #include "nsConsoleMessage.h" #include "nsIClassInfoImpl.h" #if defined(ANDROID) @@ -61,78 +60,117 @@ using namespace mozilla; NS_IMPL_THREADSAFE_ADDREF(nsConsoleService) NS_IMPL_THREADSAFE_RELEASE(nsConsoleService) NS_IMPL_CLASSINFO(nsConsoleService, NULL, nsIClassInfo::THREADSAFE | nsIClassInfo::SINGLETON, NS_CONSOLESERVICE_CID) NS_IMPL_QUERY_INTERFACE1_CI(nsConsoleService, nsIConsoleService) NS_IMPL_CI_INTERFACE_GETTER1(nsConsoleService, nsIConsoleService) nsConsoleService::nsConsoleService() - : mMessages(nsnull), mCurrent(0), mFull(false), mListening(false), mLock("nsConsoleService.mLock") + : mMessages(nsnull) + , mCurrent(0) + , mFull(false) + , mDeliveringMessage(false) + , mLock("nsConsoleService.mLock") { // XXX grab this from a pref! // hm, but worry about circularity, bc we want to be able to report // prefs errs... mBufferSize = 250; } nsConsoleService::~nsConsoleService() { PRUint32 i = 0; while (i < mBufferSize && mMessages[i] != nsnull) { NS_RELEASE(mMessages[i]); i++; } -#ifdef DEBUG_mccabe - if (mListeners.Count() != 0) { - fprintf(stderr, - "WARNING - %d console error listeners still registered!\n" - "More calls to nsIConsoleService::UnregisterListener needed.\n", - mListeners.Count()); - } - -#endif - if (mMessages) nsMemory::Free(mMessages); } nsresult nsConsoleService::Init() { mMessages = (nsIConsoleMessage **) nsMemory::Alloc(mBufferSize * sizeof(nsIConsoleMessage *)); if (!mMessages) return NS_ERROR_OUT_OF_MEMORY; // Array elements should be 0 initially for circular buffer algorithm. memset(mMessages, 0, mBufferSize * sizeof(nsIConsoleMessage *)); + mListeners.Init(); + return NS_OK; } -static bool snapshot_enum_func(nsHashKey *key, void *data, void* closure) +namespace { + +class LogMessageRunnable : public nsRunnable { - nsCOMArray<nsIConsoleListener> *array = - reinterpret_cast<nsCOMArray<nsIConsoleListener> *>(closure); +public: + LogMessageRunnable(nsIConsoleMessage* message, nsConsoleService* service) + : mMessage(message) + , mService(service) + { } + + void AddListener(nsIConsoleListener* listener) { + mListeners.AppendObject(listener); + } + + NS_DECL_NSIRUNNABLE + +private: + nsCOMPtr<nsIConsoleMessage> mMessage; + nsRefPtr<nsConsoleService> mService; + nsCOMArray<nsIConsoleListener> mListeners; +}; - // Copy each element into the temporary nsCOMArray... - array->AppendObject((nsIConsoleListener*)data); - return true; +NS_IMETHODIMP +LogMessageRunnable::Run() +{ + MOZ_ASSERT(NS_IsMainThread()); + + mService->SetIsDelivering(); + + for (PRInt32 i = 0; i < mListeners.Count(); ++i) + mListeners[i]->Observe(mMessage); + + mService->SetDoneDelivering(); + + return NS_OK; } +PLDHashOperator +CollectCurrentListeners(nsISupports* aKey, nsIConsoleListener* aValue, + void* closure) +{ + LogMessageRunnable* r = static_cast<LogMessageRunnable*>(closure); + r->AddListener(aValue); + return PL_DHASH_NEXT; +} + +} // anonymous namespace + // nsIConsoleService methods NS_IMETHODIMP nsConsoleService::LogMessage(nsIConsoleMessage *message) { if (message == nsnull) return NS_ERROR_INVALID_ARG; - nsCOMArray<nsIConsoleListener> listenersSnapshot; + if (NS_IsMainThread() && mDeliveringMessage) { + NS_WARNING("Some console listener threw an error while inside itself. Discarding this message"); + return NS_ERROR_FAILURE; + } + + nsRefPtr<LogMessageRunnable> r = new LogMessageRunnable(message, this); nsIConsoleMessage *retiredMessage; NS_ADDREF(message); // early, in case it's same as replaced below. /* * Lock while updating buffer, and while taking snapshot of * listeners array. */ @@ -161,46 +199,22 @@ nsConsoleService::LogMessage(nsIConsoleM mCurrent = 0; // wrap around. mFull = true; } /* * Copy the listeners into the snapshot array - in case a listener * is removed during an Observe(...) notification... */ - mListeners.Enumerate(snapshot_enum_func, &listenersSnapshot); + mListeners.EnumerateRead(CollectCurrentListeners, r); } if (retiredMessage != nsnull) NS_RELEASE(retiredMessage); - /* - * Iterate through any registered listeners and tell them about - * the message. We use the mListening flag to guard against - * recursive message logs. This could sometimes result in - * listeners being skipped because of activity on other threads, - * when we only care about the recursive case. - */ - nsCOMPtr<nsIConsoleListener> listener; - PRInt32 snapshotCount = listenersSnapshot.Count(); - - { - MutexAutoLock lock(mLock); - if (mListening) - return NS_OK; - mListening = true; - } - - for (PRInt32 i = 0; i < snapshotCount; i++) { - listenersSnapshot[i]->Observe(message); - } - - { - MutexAutoLock lock(mLock); - mListening = false; - } + NS_DispatchToMainThread(r); return NS_OK; } NS_IMETHODIMP nsConsoleService::LogStringMessage(const PRUnichar *message) { nsConsoleMessage *msg = new nsConsoleMessage(message); @@ -260,73 +274,54 @@ nsConsoleService::GetMessageArray(nsICon } *count = resultSize; *messages = messageArray; return NS_OK; } NS_IMETHODIMP -nsConsoleService::RegisterListener(nsIConsoleListener *listener) { - nsresult rv; - - /* - * Store a threadsafe proxy to the listener rather than the - * listener itself; we want the console service to be callable - * from any thread, but listeners can be implemented in - * thread-specific ways, and we always want to call them on their - * originating thread. JavaScript is the motivating example. - */ - nsCOMPtr<nsIConsoleListener> proxiedListener; - - rv = GetProxyForListener(listener, getter_AddRefs(proxiedListener)); - if (NS_FAILED(rv)) - return rv; +nsConsoleService::RegisterListener(nsIConsoleListener *listener) +{ + if (!NS_IsMainThread()) { + NS_ERROR("nsConsoleService::RegisterListener is main thread only."); + return NS_ERROR_NOT_SAME_THREAD; + } - { - MutexAutoLock lock(mLock); - nsISupportsKey key(listener); + nsCOMPtr<nsISupports> canonical = do_QueryInterface(listener); - /* - * Put the proxy event listener into a hashtable using the *real* - * listener as the key. - * - * This is necessary because proxy objects do *not* maintain - * nsISupports identity. Therefore, since GetProxyForListener(...) - * can return different proxies for the same object (see bug #85831) - * we need to use the real object as the unique key... - */ - mListeners.Put(&key, proxiedListener); + MutexAutoLock lock(mLock); + if (mListeners.GetWeak(canonical)) { + // Reregistering a listener isn't good + return NS_ERROR_FAILURE; } + mListeners.Put(canonical, listener); return NS_OK; } NS_IMETHODIMP -nsConsoleService::UnregisterListener(nsIConsoleListener *listener) { +nsConsoleService::UnregisterListener(nsIConsoleListener *listener) +{ + if (!NS_IsMainThread()) { + NS_ERROR("nsConsoleService::UnregisterListener is main thread only."); + return NS_ERROR_NOT_SAME_THREAD; + } + + nsCOMPtr<nsISupports> canonical = do_QueryInterface(listener); + MutexAutoLock lock(mLock); - nsISupportsKey key(listener); - mListeners.Remove(&key); + if (!mListeners.GetWeak(canonical)) { + // Unregistering a listener that was never registered? + return NS_ERROR_FAILURE; + } + mListeners.Remove(canonical); return NS_OK; } -nsresult -nsConsoleService::GetProxyForListener(nsIConsoleListener* aListener, - nsIConsoleListener** aProxy) -{ - /* - * Would it be better to catch that case and leave the listener unproxied? - */ - return NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, - NS_GET_IID(nsIConsoleListener), - aListener, - NS_PROXY_ASYNC | NS_PROXY_ALWAYS, - (void**) aProxy); -} - NS_IMETHODIMP nsConsoleService::Reset() { /* * Make sure nobody trips into the buffer while it's being reset */ MutexAutoLock lock(mLock);
--- a/xpcom/base/nsConsoleService.h +++ b/xpcom/base/nsConsoleService.h @@ -41,52 +41,62 @@ #ifndef __nsconsoleservice_h__ #define __nsconsoleservice_h__ #include "mozilla/Attributes.h" #include "mozilla/Mutex.h" #include "nsCOMPtr.h" -#include "nsHashtable.h" +#include "nsInterfaceHashtable.h" +#include "nsHashKeys.h" #include "nsIConsoleService.h" class nsConsoleService MOZ_FINAL : public nsIConsoleService { public: nsConsoleService(); nsresult Init(); NS_DECL_ISUPPORTS NS_DECL_NSICONSOLESERVICE + void SetIsDelivering() { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mDeliveringMessage); + mDeliveringMessage = true; + } + + void SetDoneDelivering() { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mDeliveringMessage); + mDeliveringMessage = false; + } + private: ~nsConsoleService(); - // build (or find) a proxy for the listener - nsresult GetProxyForListener(nsIConsoleListener* aListener, - nsIConsoleListener** aProxy); - // Circular buffer of saved messages nsIConsoleMessage **mMessages; // How big? PRUint32 mBufferSize; // Index of slot in mMessages that'll be filled by *next* log message PRUint32 mCurrent; // Is the buffer full? (Has mCurrent wrapped around at least once?) bool mFull; - // Listeners to notify whenever a new message is logged. - nsSupportsHashtable mListeners; + // Are we currently delivering a console message on the main thread? If + // so, we suppress incoming messages on the main thread only, to avoid + // infinite repitition. + bool mDeliveringMessage; - // Current listener being notified of a logged error - to prevent - // stack overflows. - bool mListening; + // Listeners to notify whenever a new message is logged. + nsInterfaceHashtable<nsISupportsHashKey, nsIConsoleListener> mListeners; // To serialize interesting methods. mozilla::Mutex mLock; }; #endif /* __nsconsoleservice_h__ */
--- a/xpcom/build/XPCOMModule.inc +++ b/xpcom/build/XPCOMModule.inc @@ -19,18 +19,16 @@ COMPONENT(SUPPORTSARRAY, nsSupportsArray::Create) COMPONENT(ARRAY, nsArrayConstructor) COMPONENT(CONSOLESERVICE, nsConsoleServiceConstructor) COMPONENT(EXCEPTIONSERVICE, nsExceptionServiceConstructor) COMPONENT(ATOMSERVICE, nsAtomServiceConstructor) COMPONENT(OBSERVERSERVICE, nsObserverService::Create) - COMPONENT(XPCOMPROXY, nsProxyObjectManager::Create) - COMPONENT(TIMER, nsTimerImplConstructor) #define COMPONENT_SUPPORTS(TYPE, Type) \ COMPONENT(SUPPORTS_##TYPE, nsSupports##Type##ImplConstructor) COMPONENT_SUPPORTS(ID, ID) COMPONENT_SUPPORTS(STRING, String) COMPONENT_SUPPORTS(CSTRING, CString)
--- a/xpcom/build/nsXPComInit.cpp +++ b/xpcom/build/nsXPComInit.cpp @@ -73,19 +73,16 @@ #include "nsComponentManager.h" #include "nsCategoryManagerUtils.h" #include "nsIServiceManager.h" #include "nsThreadManager.h" #include "nsThreadPool.h" -#include "nsIProxyObjectManager.h" -#include "nsProxyEventPrivate.h" // access to the impl of nsProxyObjectManager for the generic factory registration. - #include "xptinfo.h" #include "nsIInterfaceInfoManager.h" #include "xptiprivate.h" #include "nsTimerImpl.h" #include "TimerThread.h" #include "nsThread.h" @@ -268,17 +265,16 @@ static NS_DEFINE_CID(kSimpleUnicharStrea NS_DEFINE_NAMED_CID(NS_CHROMEREGISTRY_CID); NS_DEFINE_NAMED_CID(NS_CHROMEPROTOCOLHANDLER_CID); NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsChromeRegistry, nsChromeRegistry::GetSingleton) NS_GENERIC_FACTORY_CONSTRUCTOR(nsChromeProtocolHandler) #define NS_PERSISTENTPROPERTIES_CID NS_IPERSISTENTPROPERTIES_CID /* sigh */ -#define NS_XPCOMPROXY_CID NS_PROXYEVENT_MANAGER_CID static already_AddRefed<nsIFactory> CreateINIParserFactory(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry) { nsIFactory* f = new nsINIParserFactory(); f->AddRef(); return f; @@ -660,18 +656,16 @@ ShutdownXPCOM(nsIServiceManager* servMgr // here again: NS_IF_RELEASE(servMgr); // Shutdown global servicemanager if (nsComponentManagerImpl::gComponentManager) { nsComponentManagerImpl::gComponentManager->FreeServices(); } - nsProxyObjectManager::Shutdown(); - // Release the directory service NS_IF_RELEASE(nsDirectoryService::gService); nsCycleCollector_shutdown(); if (moduleLoaders) { bool more; nsCOMPtr<nsISupports> el;
--- a/xpcom/components/nsCategoryManager.cpp +++ b/xpcom/components/nsCategoryManager.cpp @@ -54,17 +54,16 @@ #include "nsComponentManagerUtils.h" #include "nsServiceManagerUtils.h" #include "nsIObserver.h" #include "nsIObserverService.h" #include "nsReadableUtils.h" #include "nsCRT.h" #include "nsQuickSort.h" #include "nsEnumeratorUtils.h" -#include "nsIProxyObjectManager.h" #include "nsThreadUtils.h" #include "mozilla/Services.h" #include "ManifestParser.h" #include "mozilla/FunctionTimer.h" using namespace mozilla; class nsIComponentLoaderManager; @@ -492,53 +491,81 @@ inline CategoryNode* nsCategoryManager::get_category(const char* aName) { CategoryNode* node; if (!mTable.Get(aName, &node)) { return nsnull; } return node; } +namespace { + +class CategoryNotificationRunnable : public nsRunnable +{ +public: + CategoryNotificationRunnable(nsISupports* aSubject, + const char* aTopic, + const char* aData) + : mSubject(aSubject) + , mTopic(aTopic) + , mData(aData) + { } + + NS_DECL_NSIRUNNABLE + +private: + nsCOMPtr<nsISupports> mSubject; + const char* mTopic; + NS_ConvertUTF8toUTF16 mData; +}; + +NS_IMETHODIMP +CategoryNotificationRunnable::Run() +{ + nsCOMPtr<nsIObserverService> observerService = + mozilla::services::GetObserverService(); + if (observerService) + observerService->NotifyObservers(mSubject, mTopic, mData.get()); + + return NS_OK; +} + +} // anonymous namespace + + void nsCategoryManager::NotifyObservers( const char *aTopic, const char *aCategoryName, const char *aEntryName ) { if (mSuppressNotifications) return; - nsCOMPtr<nsIObserverService> observerService = - mozilla::services::GetObserverService(); - if (!observerService) - return; - - nsCOMPtr<nsIObserverService> obsProxy; - NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, - NS_GET_IID(nsIObserverService), - observerService, - NS_PROXY_ASYNC, - getter_AddRefs(obsProxy)); - if (!obsProxy) - return; + nsRefPtr<CategoryNotificationRunnable> r; if (aEntryName) { nsCOMPtr<nsISupportsCString> entry (do_CreateInstance (NS_SUPPORTS_CSTRING_CONTRACTID)); if (!entry) return; nsresult rv = entry->SetData(nsDependentCString(aEntryName)); if (NS_FAILED(rv)) return; - obsProxy->NotifyObservers(entry, aTopic, - NS_ConvertUTF8toUTF16(aCategoryName).get()); + r = new CategoryNotificationRunnable(entry, aTopic, aCategoryName); } else { - obsProxy->NotifyObservers(this, aTopic, - NS_ConvertUTF8toUTF16(aCategoryName).get()); + r = new CategoryNotificationRunnable(this, aTopic, aCategoryName); + } + + if (NS_IsMainThread()) { + r->Run(); + } + else { + NS_DispatchToMainThread(r); } } NS_IMETHODIMP nsCategoryManager::GetCategoryEntry( const char *aCategoryName, const char *aEntryName, char **_retval ) {
--- a/xpcom/components/nsCategoryManager.h +++ b/xpcom/components/nsCategoryManager.h @@ -152,17 +152,17 @@ public: private: static nsCategoryManager* gCategoryManager; nsCategoryManager(); ~nsCategoryManager(); CategoryNode* get_category(const char* aName); void NotifyObservers(const char* aTopic, - const char* aCategoryName, + const char* aCategoryName, // must be a static string const char* aEntryName); PLArenaPool mArena; nsClassHashtable<nsDepCharHashKey, CategoryNode> mTable; mozilla::Mutex mLock; bool mSuppressNotifications; };
--- a/xpcom/components/nsNativeComponentLoader.cpp +++ b/xpcom/components/nsNativeComponentLoader.cpp @@ -59,17 +59,16 @@ #include "nsComponentManager.h" #include "ManifestParser.h" // for LogMessage #include "nsCRTGlue.h" #include "nsThreadUtils.h" #include "nsTraceRefcntImpl.h" #include "nsILocalFile.h" -#include "nsIProxyObjectManager.h" #ifdef XP_WIN #include <windows.h> #endif #ifdef XP_MACOSX #include <signal.h> #endif
deleted file mode 100644 --- a/xpcom/proxy/Makefile.in +++ /dev/null @@ -1,49 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is mozilla.org Code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = xpcom -DIRS = public src - -include $(topsrcdir)/config/rules.mk -
deleted file mode 100644 --- a/xpcom/proxy/public/Makefile.in +++ /dev/null @@ -1,57 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = xpcom -XPIDL_MODULE = proxyObject - -EXPORTS = \ - nsProxiedService.h \ - $(NULL) - -XPIDLSRCS = \ - nsIProxyObjectManager.idl \ - $(NULL) - -include $(topsrcdir)/config/rules.mk -
deleted file mode 100644 --- a/xpcom/proxy/public/nsIProxyObjectManager.idl +++ /dev/null @@ -1,144 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Doug Turner <dougt@netscape.com> (Original Author) - * Dan Mosedale <dmose@netscape.com> - * Darin Fisher <darin@meer.net> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsISupports.idl" - -interface nsIEventTarget; - -/** - * An interface for the proxy object manager. - * - * See http://www.mozilla.org/projects/xpcom/Proxies.html - */ -[scriptable, uuid(ee8ce1e3-0319-4bd9-8f70-7258b21c7733)] -interface nsIProxyObjectManager : nsISupports -{ - /** - * Construct a proxy object that invokes methods on the real object - * synchronously (i.e., the calling thread is blocked until the real method - * call returns). This flag causes methods invoked on the proxy object to - * emmulate a real method call. - * - * For C++ callers, NS_PROXY_SYNC is a synonym for this flag. - */ - const long INVOKE_SYNC = 0x0001; - - /** - * Construct a proxy object that invokes methods on the real object - * asynchronously (i.e., the calling thread does not wait for the real - * method call to occur). - * - * WARNING: do not pass pointers into the stack when using this flag. - * - * For C++ callers, NS_PROXY_ASYNC is a synonym for this flag. - */ - const long INVOKE_ASYNC = 0x0002; - - /** - * Always create the proxy object even if for same thread as current thread. - * - * For C++ callers, NS_PROXY_ALWAYS is a synonym for this flag. - */ - const long FORCE_PROXY_CREATION = 0x0004; - - /** - * Create a proxy for the given object. The proxy implements the specified - * interface, but when its methods are invoked, it causes the corresponding - * method on the actual object to be called via the designated event - * target. Typically, the event target identifies a thread where the - * method call should occur. - * - * @param target - * If target is null, then the current thread is used as the target. - * Otherwise, target identifies the nsIEventTarget from which proxy - * method calls should be executed. - * @param iid - * Identifies the interface being proxied. The given object must QI to - * this type. - * @param object - * The object being proxied. - * @param proxyType - * Specifies the type of proxy to construct. Either INVOKE_SYNC or - * INVOKE_ASYNC must be specified. FORCE_PROXY_CREATION may be bit-wise - * OR'd with either of those flags. - * @param result - * This param holds the resulting proxy object upon successful return. - */ - void getProxyForObject(in nsIEventTarget target, - in nsIIDRef iid, - in nsISupports object, - in PRInt32 proxyType, - [iid_is(iid),retval] out nsQIResult result); -}; - - -%{C++ -/** - * convenience macros - */ -#define NS_PROXY_SYNC nsIProxyObjectManager::INVOKE_SYNC -#define NS_PROXY_ASYNC nsIProxyObjectManager::INVOKE_ASYNC -#define NS_PROXY_ALWAYS nsIProxyObjectManager::FORCE_PROXY_CREATION - -/** - * Pass this value as the target to {NS_}GetProxyForObject to specify the current - * thread as the target for the proxy object. - */ -#define NS_PROXY_TO_CURRENT_THREAD ((nsIEventTarget *) 0) - -/** - * Pass this value as the target to NS_GetProxyForObject to specify the main - * thread as the target for the proxy object. - */ -#define NS_PROXY_TO_MAIN_THREAD ((nsIEventTarget *) 1) - -#ifdef MOZILLA_INTERNAL_API -/** - * Helper function for code that already has a link-time dependency on the - * internal API (MOZILLA_INTERNAL_API) and needs to get proxies in a bunch of - * different places. This way, the caller isn't forced to get the proxy object - * manager themselves every single time, thus making the calling code more - * readable. The parameters are the same as for GetProxyForObject. - */ -extern nsresult -NS_GetProxyForObject(nsIEventTarget *target, REFNSIID iid, nsISupports* object, - PRInt32 proxyType, void** result); -#endif -%}
deleted file mode 100644 --- a/xpcom/proxy/public/nsProxiedService.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Pierre Phaneuf <pp@ludusdesign.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsProxiedService_h__ -#define nsProxiedService_h__ - -#include "nsServiceManagerUtils.h" -#include "nsIProxyObjectManager.h" -#include "nsXPCOMCIDInternal.h" - -//////////////////////////////////////////////////////////////////////////////// -// NS_WITH_PROXIED_SERVICE: macro to make using services that need to be proxied -// before using them easier. -// Now you can replace this: -// { -// nsresult rv; -// nsCOMPtr<nsIMyService> pIMyService = -// do_GetService(kMyServiceCID, &rv); -// if(NS_FAILED(rv)) -// return; -// nsCOMPtr<nsIProxyObjectManager> pIProxyObjectManager = -// do_GetService(kProxyObjectManagerCID, &rv); -// if(NS_FAILED(rv)) -// return; -// nsIMyService pIProxiedObject = NULL; -// rv = pIProxyObjectManager->GetProxyForObject(pIDispatchTarget, -// NS_GET_IID(nsIMyService), -// pIMyService, NS_PROXY_SYNC, -// (void**)&pIProxiedObject); -// pIProxiedObject->DoIt(...); // Executed on same thread as pIProxyQueue -// ... -// pIProxiedObject->Release(); // Must be done as not managed for you. -// } -// with this: -// { -// nsresult rv; -// NS_WITH_PROXIED_SERVICE(nsIMyService, pIMyService, kMyServiceCID, -// pIDispatchTarget, &rv); -// if(NS_FAILED(rv)) -// return; -// pIMyService->DoIt(...); // Executed on the same thread as pIProxyQueue -// } -// and the automatic destructor will take care of releasing the service and -// the proxied object for you. -// -// Note that this macro requires you to link with the xpcom DLL to pick up the -// static member functions from nsServiceManager. - -#define NS_WITH_PROXIED_SERVICE(T, var, cid, Q, rvAddr) \ - nsProxiedService _serv##var(cid, NS_GET_IID(T), Q, false, rvAddr); \ - T* var = (T*)(nsISupports*)_serv##var; - -#define NS_WITH_ALWAYS_PROXIED_SERVICE(T, var, cid, Q, rvAddr) \ - nsProxiedService _serv##var(cid, NS_GET_IID(T), Q, true, rvAddr); \ - T* var = (T*)(nsISupports*)_serv##var; - -//////////////////////////////////////////////////////////////////////////////// -// nsProxiedService -//////////////////////////////////////////////////////////////////////////////// - -class NS_STACK_CLASS nsProxiedService -{ -public: - nsProxiedService(const nsCID &aClass, const nsIID &aIID, - nsIEventTarget* aTarget, bool always, nsresult* rv) - { - nsCOMPtr<nsISupports> svc = do_GetService(aClass, rv); - if (NS_SUCCEEDED(*rv)) - InitProxy(svc, aIID, aTarget, always, rv); - } - - nsProxiedService(const char* aContractID, const nsIID &aIID, - nsIEventTarget* aTarget, bool always, nsresult* rv) - { - nsCOMPtr<nsISupports> svc = do_GetService(aContractID, rv); - if (NS_SUCCEEDED(*rv)) - InitProxy(svc, aIID, aTarget, always, rv); - } - - operator nsISupports*() const - { - return mProxiedService; - } - -private: - - void InitProxy(nsISupports *aObj, const nsIID &aIID, - nsIEventTarget* aTarget, bool always, nsresult*rv) - { - PRInt32 proxyType = NS_PROXY_SYNC; - if (always) - proxyType |= NS_PROXY_ALWAYS; - - nsCOMPtr<nsIProxyObjectManager> proxyObjMgr = do_GetService(NS_XPCOMPROXY_CONTRACTID, rv); - if (NS_FAILED(*rv)) - return; - - *rv = proxyObjMgr->GetProxyForObject(aTarget, - aIID, - aObj, - proxyType, - getter_AddRefs(mProxiedService)); - } - - nsCOMPtr<nsISupports> mProxiedService; -}; - -#endif // nsProxiedService_h__
deleted file mode 100644 --- a/xpcom/proxy/src/Makefile.in +++ /dev/null @@ -1,66 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = xpcom -LIBRARY_NAME = xpcomproxy_s -MOZILLA_INTERNAL_API = 1 - - -CPPSRCS = \ - nsProxyEvent.cpp \ - nsProxyEventClass.cpp \ - nsProxyEventObject.cpp \ - nsProxyObjectManager.cpp \ - $(NULL) - -DEFINES += -D_IMPL_NS_COM -DEXPORT_XPTC_API -LOCAL_INCLUDES += -I$(top_srcdir)/xpcom/threads/ - -# No shared lib; Force creation of static lib -FORCE_STATIC_LIB = 1 - - -include $(topsrcdir)/config/rules.mk - -LOCAL_INCLUDES += -I$(srcdir)/../../reflect/xptinfo/src
deleted file mode 100644 --- a/xpcom/proxy/src/nsProxyEvent.cpp +++ /dev/null @@ -1,513 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim:set ts=4 sw=4 sts=4 ci et: */ -/* - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** - * - * This Original Code has been modified by IBM Corporation. - * Modifications made by IBM described herein are - * Copyright (c) International Business Machines - * Corporation, 2000 - * - * Modifications to Mozilla code or documentation - * identified per MPL Section 3.3 - * - * Date Modified by Description of modification - * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2 - */ - -#include "nsProxyEventPrivate.h" -#include "nsProxyRelease.h" -#include "nsIProxyObjectManager.h" -#include "nsCRT.h" - -#include "pratom.h" -#include "prmem.h" -#include "xptcall.h" - -#include "nsXPCOMCID.h" -#include "nsServiceManagerUtils.h" -#include "nsIComponentManager.h" -#include "nsThreadUtils.h" -#include "nsEventQueue.h" -#include "nsMemory.h" - -using namespace mozilla; - -/** - * Map the nsAUTF8String, nsUTF8String classes to the nsACString and - * nsCString classes respectively for now. These defines need to be removed - * once Jag lands his nsUTF8String implementation. - */ -#define nsAUTF8String nsACString -#define nsUTF8String nsCString - -class nsProxyCallCompletedEvent : public nsRunnable -{ -public: - nsProxyCallCompletedEvent(nsProxyObjectCallInfo *info) - : mInfo(info) - {} - - NS_DECL_NSIRUNNABLE - - NS_IMETHOD QueryInterface(REFNSIID aIID, void **aResult); - -private: - nsProxyObjectCallInfo *mInfo; -}; - -NS_IMETHODIMP -nsProxyCallCompletedEvent::Run() -{ - NS_ASSERTION(mInfo, "no info"); - mInfo->SetCompleted(); - return NS_OK; -} - -NS_DEFINE_IID(kFilterIID, NS_PROXYEVENT_FILTER_IID); - -NS_IMETHODIMP -nsProxyCallCompletedEvent::QueryInterface(REFNSIID aIID, void **aResult) -{ - // We are explicitly breaking XPCOM rules here by returning a different - // object from QueryInterface. We do this so that - // nsProxyThreadFilter::AcceptEvent can know whether we are an event that - // needs to be allowed through during a synchronous proxy call. - if (aIID.Equals(kFilterIID)) { - *aResult = mInfo; - mInfo->AddRef(); - return NS_OK; - } - return nsRunnable::QueryInterface(aIID, aResult); -} - -//----------------------------------------------------------------------------- - -NS_IMETHODIMP -nsProxyObject::nsProxyObjectDestructorEvent::Run() -{ - delete mDoomed; - return NS_OK; -} - -//----------------------------------------------------------------------------- - -nsProxyObjectCallInfo::nsProxyObjectCallInfo(nsProxyEventObject* owner, - const XPTMethodDescriptor *methodInfo, - PRUint32 methodIndex, - nsXPTCVariant* parameterList, - PRUint32 parameterCount) : - mResult(NS_ERROR_FAILURE), - mMethodInfo(methodInfo), - mMethodIndex(methodIndex), - mParameterList(parameterList), - mParameterCount(parameterCount), - mCompleted(0), - mOwner(owner) -{ - NS_ASSERTION(owner, "No nsProxyObject!"); - NS_ASSERTION(methodInfo, "No nsXPTMethodInfo!"); - - RefCountInInterfacePointers(true); - if (mOwner->GetProxyType() & NS_PROXY_ASYNC) - CopyStrings(true); -} - -nsProxyObjectCallInfo::~nsProxyObjectCallInfo() -{ - RefCountInInterfacePointers(false); - if (mOwner->GetProxyType() & NS_PROXY_ASYNC) - CopyStrings(false); - - mOwner = nsnull; - - if (mParameterList) - free(mParameterList); -} - -NS_IMETHODIMP -nsProxyObjectCallInfo::QueryInterface(REFNSIID aIID, void **aResult) -{ - if (aIID.Equals(kFilterIID)) { - *aResult = this; - AddRef(); - return NS_OK; - } - return nsRunnable::QueryInterface(aIID, aResult); -} - -NS_IMETHODIMP -nsProxyObjectCallInfo::Run() -{ - PROXY_LOG(("PROXY(%p): Run\n", this)); - - mResult = NS_InvokeByIndex(mOwner->GetProxiedInterface(), - mMethodIndex, - mParameterCount, - mParameterList); - - if (IsSync()) { - PostCompleted(); - } - - return NS_OK; -} - -void -nsProxyObjectCallInfo::RefCountInInterfacePointers(bool addRef) -{ - for (PRUint32 i = 0; i < mParameterCount; i++) - { - nsXPTParamInfo paramInfo = mMethodInfo->params[i]; - - if (paramInfo.GetType().IsInterfacePointer() ) - { - nsISupports* anInterface = nsnull; - - if (paramInfo.IsIn()) - { - anInterface = ((nsISupports*)mParameterList[i].val.p); - - if (anInterface) - { - if (addRef) - anInterface->AddRef(); - else - anInterface->Release(); - - } - } - } - } -} - -void -nsProxyObjectCallInfo::CopyStrings(bool copy) -{ - for (PRUint32 i = 0; i < mParameterCount; i++) - { - const nsXPTParamInfo paramInfo = mMethodInfo->params[i]; - - if (paramInfo.IsIn()) - { - const nsXPTType& type = paramInfo.GetType(); - uint8 type_tag = type.TagPart(); - void *ptr = mParameterList[i].val.p; - - if (!ptr) - continue; - - if (copy) - { - switch (type_tag) - { - case nsXPTType::T_CHAR_STR: - mParameterList[i].val.p = - PL_strdup((const char *)ptr); - break; - case nsXPTType::T_WCHAR_STR: - mParameterList[i].val.p = - nsCRT::strdup((const PRUnichar *)ptr); - break; - case nsXPTType::T_DOMSTRING: - case nsXPTType::T_ASTRING: - mParameterList[i].val.p = - new nsString(*((nsAString*) ptr)); - break; - case nsXPTType::T_CSTRING: - mParameterList[i].val.p = - new nsCString(*((nsACString*) ptr)); - break; - case nsXPTType::T_UTF8STRING: - mParameterList[i].val.p = - new nsUTF8String(*((nsAUTF8String*) ptr)); - break; - default: - // Other types are ignored - break; - } - } - else - { - switch (type_tag) - { - case nsXPTType::T_CHAR_STR: - PL_strfree((char*) ptr); - break; - case nsXPTType::T_WCHAR_STR: - nsCRT::free((PRUnichar*)ptr); - break; - case nsXPTType::T_DOMSTRING: - case nsXPTType::T_ASTRING: - delete (nsString*) ptr; - break; - case nsXPTType::T_CSTRING: - delete (nsCString*) ptr; - break; - case nsXPTType::T_UTF8STRING: - delete (nsUTF8String*) ptr; - break; - default: - // Other types are ignored - break; - } - } - } - } -} - -bool -nsProxyObjectCallInfo::GetCompleted() -{ - return !!mCompleted; -} - -void -nsProxyObjectCallInfo::SetCompleted() -{ - PROXY_LOG(("PROXY(%p): SetCompleted\n", this)); - PR_ATOMIC_SET(&mCompleted, 1); -} - -void -nsProxyObjectCallInfo::PostCompleted() -{ - PROXY_LOG(("PROXY(%p): PostCompleted\n", this)); - - if (mCallersTarget) { - nsCOMPtr<nsIRunnable> event = - new nsProxyCallCompletedEvent(this); - if (event && - NS_SUCCEEDED(mCallersTarget->Dispatch(event, NS_DISPATCH_NORMAL))) - return; - } - - // OOM? caller does not have a target? This is an error! - NS_WARNING("Failed to dispatch nsProxyCallCompletedEvent"); - SetCompleted(); -} - -nsIEventTarget* -nsProxyObjectCallInfo::GetCallersTarget() -{ - return mCallersTarget; -} - -void -nsProxyObjectCallInfo::SetCallersTarget(nsIEventTarget* target) -{ - mCallersTarget = target; -} - -nsProxyObject::nsProxyObject(nsIEventTarget *target, PRInt32 proxyType, - nsISupports *realObject) : - mProxyType(proxyType), - mTarget(target), - mRealObject(realObject), - mFirst(nsnull) -{ - MOZ_COUNT_CTOR(nsProxyObject); - -#ifdef DEBUG - nsCOMPtr<nsISupports> canonicalTarget = do_QueryInterface(target); - NS_ASSERTION(target == canonicalTarget, - "Non-canonical nsISupports passed to nsProxyObject constructor"); -#endif -} - -nsProxyObject::~nsProxyObject() -{ - // Proxy the release of mRealObject to protect against it being deleted on - // the wrong thread. - nsISupports *doomed = nsnull; - mRealObject.swap(doomed); - NS_ProxyRelease(mTarget, doomed); - - MOZ_COUNT_DTOR(nsProxyObject); -} - -NS_IMETHODIMP_(nsrefcnt) -nsProxyObject::AddRef() -{ - MutexAutoLock lock(nsProxyObjectManager::GetInstance()->GetLock()); - return LockedAddRef(); -} - -NS_IMETHODIMP_(nsrefcnt) -nsProxyObject::Release() -{ - MutexAutoLock lock(nsProxyObjectManager::GetInstance()->GetLock()); - return LockedRelease(); -} - -nsrefcnt -nsProxyObject::LockedAddRef() -{ - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsProxyObject", sizeof(nsProxyObject)); - return mRefCnt; -} - -nsrefcnt -nsProxyObject::LockedRelease() -{ - NS_PRECONDITION(0 != mRefCnt, "dup release"); - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsProxyObject"); - if (mRefCnt) - return mRefCnt; - - nsProxyObjectManager *pom = nsProxyObjectManager::GetInstance(); - pom->LockedRemove(this); - - MutexAutoUnlock unlock(pom->GetLock()); - delete this; - - return 0; -} - -NS_IMETHODIMP -nsProxyObject::QueryInterface(REFNSIID aIID, void **aResult) -{ - if (aIID.Equals(GetIID())) { - *aResult = this; - AddRef(); - return NS_OK; - } - - if (aIID.Equals(NS_GET_IID(nsISupports))) { - *aResult = static_cast<nsISupports*>(this); - AddRef(); - return NS_OK; - } - - nsProxyObjectManager *pom = nsProxyObjectManager::GetInstance(); - NS_ASSERTION(pom, "Deleting a proxy without a global proxy-object-manager."); - - MutexAutoLock lock(pom->GetLock()); - return LockedFind(aIID, aResult); -} - -nsresult -nsProxyObject::LockedFind(REFNSIID aIID, void **aResult) -{ - // This method is only called when the global lock is held. -#ifdef DEBUG - nsProxyObjectManager::GetInstance()->GetLock().AssertCurrentThreadOwns(); -#endif - - nsProxyEventObject *peo; - - for (peo = mFirst; peo; peo = peo->mNext) { - if (peo->GetClass()->GetProxiedIID().Equals(aIID)) { - *aResult = static_cast<nsISupports*>(peo->mXPTCStub); - peo->LockedAddRef(); - return NS_OK; - } - } - - nsProxyEventObject *newpeo; - - // Both GetClass and QueryInterface call out to XPCOM, so we unlock for them - nsProxyObjectManager* pom = nsProxyObjectManager::GetInstance(); - { - MutexAutoUnlock unlock(pom->GetLock()); - - nsProxyEventClass *pec; - nsresult rv = pom->GetClass(aIID, &pec); - if (NS_FAILED(rv)) - return rv; - - nsISomeInterface* newInterface; - rv = mRealObject->QueryInterface(aIID, (void**) &newInterface); - if (NS_FAILED(rv)) - return rv; - - newpeo = new nsProxyEventObject(this, pec, - already_AddRefed<nsISomeInterface>(newInterface), &rv); - if (!newpeo) { - NS_RELEASE(newInterface); - return NS_ERROR_OUT_OF_MEMORY; - } - - if (NS_FAILED(rv)) { - delete newpeo; - return rv; - } - } - - // Now that we're locked again, check for races by repeating the - // linked-list check. - for (peo = mFirst; peo; peo = peo->mNext) { - if (peo->GetClass()->GetProxiedIID().Equals(aIID)) { - // Best to AddRef for our caller before unlocking. - peo->LockedAddRef(); - - { - // Deleting an nsProxyEventObject can call Release on an - // nsProxyObject, which can only happen when not holding - // the lock. - MutexAutoUnlock unlock(pom->GetLock()); - delete newpeo; - } - *aResult = static_cast<nsISupports*>(peo->mXPTCStub); - return NS_OK; - } - } - - newpeo->mNext = mFirst; - mFirst = newpeo; - - newpeo->LockedAddRef(); - - *aResult = static_cast<nsISupports*>(newpeo->mXPTCStub); - return NS_OK; -} - -void -nsProxyObject::LockedRemove(nsProxyEventObject *peo) -{ - nsProxyEventObject **i; - for (i = &mFirst; *i; i = &((*i)->mNext)) { - if (*i == peo) { - *i = peo->mNext; - return; - } - } - NS_ERROR("Didn't find nsProxyEventObject in nsProxyObject chain!"); -}
deleted file mode 100644 --- a/xpcom/proxy/src/nsProxyEventClass.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim:set ts=4 sw=4 sts=4 ci et: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Pierre Phaneuf <pp@ludusdesign.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsProxyEventPrivate.h" - -#include "nsIComponentManager.h" -#include "nsIServiceManager.h" -#include "nsCOMPtr.h" - -#include "nsMemory.h" -#include "nsHashtable.h" - -#include "xptcall.h" - -// LIFETIME_CACHE will cache class for the entire cyle of the application. -#define LIFETIME_CACHE - -static uint32 zero_methods_descriptor; - - -////////////////////////////////////////////////////////////////////////////////////////////////// -// nsProxyEventClass -////////////////////////////////////////////////////////////////////////////////////////////////// - -nsProxyEventClass::nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo) - : mIID(aIID), - mInfo(aInfo), - mDescriptors(NULL) -{ - uint16 methodCount; - if(NS_SUCCEEDED(mInfo->GetMethodCount(&methodCount))) - { - if(methodCount) - { - int wordCount = (methodCount/32)+1; - if(NULL != (mDescriptors = new uint32[wordCount])) - { - memset(mDescriptors, 0, wordCount * sizeof(uint32)); - } - } - else - { - mDescriptors = &zero_methods_descriptor; - } - } -} - -nsProxyEventClass::~nsProxyEventClass() -{ - if (mDescriptors && mDescriptors != &zero_methods_descriptor) - delete [] mDescriptors; -}
deleted file mode 100644 --- a/xpcom/proxy/src/nsProxyEventObject.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Pierre Phaneuf <pp@ludusdesign.com> - * Benjamin Smedberg <benjamin@smedbergs.us> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "prprf.h" -#include "prmem.h" - -#include "nscore.h" -#include "nsProxyEventPrivate.h" -#include "nsIThreadInternal.h" - -#include "nsServiceManagerUtils.h" - -#include "nsHashtable.h" - -#include "nsIInterfaceInfoManager.h" -#include "xptcall.h" - -using namespace mozilla; - -nsProxyEventObject::nsProxyEventObject(nsProxyObject *aParent, - nsProxyEventClass* aClass, - already_AddRefed<nsISomeInterface> aRealInterface, - nsresult *rv) - : mClass(aClass), - mProxyObject(aParent), - mRealInterface(aRealInterface), - mNext(nsnull) -{ - *rv = InitStub(aClass->GetProxiedIID()); -} - -nsProxyEventObject::~nsProxyEventObject() -{ - // This destructor must *not* be called within the POM lock - // XXX assert this! - - // mRealInterface must be released before mProxyObject so that the last - // release of the proxied object is proxied to the correct thread. - // See bug 337492. - mRealInterface = nsnull; -} - -// -// nsISupports implementation... -// - -NS_IMETHODIMP_(nsrefcnt) -nsProxyEventObject::AddRef() -{ - MutexAutoLock lock(nsProxyObjectManager::GetInstance()->GetLock()); - return LockedAddRef(); -} - -nsrefcnt -nsProxyEventObject::LockedAddRef() -{ - ++mRefCnt; - NS_LOG_ADDREF(this, mRefCnt, "nsProxyEventObject", sizeof(nsProxyEventObject)); - return mRefCnt; -} - -NS_IMETHODIMP_(nsrefcnt) -nsProxyEventObject::Release(void) -{ - { - MutexAutoLock lock(nsProxyObjectManager::GetInstance()->GetLock()); - NS_PRECONDITION(0 != mRefCnt, "dup release"); - - --mRefCnt; - NS_LOG_RELEASE(this, mRefCnt, "nsProxyEventObject"); - - if (mRefCnt) - return mRefCnt; - - mProxyObject->LockedRemove(this); - } - - // call the destructor outside of the lock so that we aren't holding the - // lock when we release the object - delete this; - return 0; -} - -NS_IMETHODIMP -nsProxyEventObject::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - if( aIID.Equals(GetClass()->GetProxiedIID()) ) - { - *aInstancePtr = static_cast<nsISupports*>(mXPTCStub); - NS_ADDREF_THIS(); - return NS_OK; - } - - return mProxyObject->QueryInterface(aIID, aInstancePtr); -} - -// -// nsXPTCStubBase implementation... -// - -nsresult -nsProxyEventObject::convertMiniVariantToVariant(const XPTMethodDescriptor *methodInfo, - nsXPTCMiniVariant * params, - nsXPTCVariant **fullParam, - uint8 *outParamCount) -{ - uint8 paramCount = methodInfo->num_args; - *outParamCount = paramCount; - *fullParam = nsnull; - - if (!paramCount) return NS_OK; - - *fullParam = (nsXPTCVariant*)malloc(sizeof(nsXPTCVariant) * paramCount); - - if (*fullParam == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - - for (int i = 0; i < paramCount; i++) - { - const nsXPTParamInfo& paramInfo = methodInfo->params[i]; - if ((GetProxyType() & NS_PROXY_ASYNC) && - (paramInfo.IsOut() || paramInfo.IsDipper())) - { - NS_WARNING("Async proxying of out parameters is not supported"); - free(*fullParam); - return NS_ERROR_PROXY_INVALID_OUT_PARAMETER; - } - uint8 flags = paramInfo.IsOut() ? nsXPTCVariant::PTR_IS_DATA : 0; - (*fullParam)[i].Init(params[i], paramInfo.GetType(), flags); - } - - return NS_OK; -} - -class nsProxyThreadFilter : public nsIThreadEventFilter -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSITHREADEVENTFILTER -}; - -NS_IMPL_THREADSAFE_ISUPPORTS1(nsProxyThreadFilter, nsIThreadEventFilter) - -NS_DEFINE_IID(kFilterIID, NS_PROXYEVENT_FILTER_IID); - -NS_IMETHODIMP_(bool) -nsProxyThreadFilter::AcceptEvent(nsIRunnable *event) -{ - PROXY_LOG(("PROXY(%p): filter event [%p]\n", this, event)); - - // If we encounter one of our proxy events that is for a synchronous method - // call, then we want to put it in our event queue for processing. Else, - // we want to allow the event to be dispatched to the thread's event queue - // for processing later once we complete the current sync method call. - - nsRefPtr<nsProxyObjectCallInfo> poci; - event->QueryInterface(kFilterIID, getter_AddRefs(poci)); - return poci && poci->IsSync(); -} - -NS_IMETHODIMP -nsProxyEventObject::CallMethod(PRUint16 methodIndex, - const XPTMethodDescriptor* methodInfo, - nsXPTCMiniVariant * params) -{ - NS_ASSERTION(methodIndex > 2, - "Calling QI/AddRef/Release through CallMethod"); - nsresult rv; - - if (XPT_MD_IS_NOTXPCOM(methodInfo->flags)) - return NS_ERROR_PROXY_INVALID_IN_PARAMETER; - - nsXPTCVariant *fullParam; - uint8 paramCount; - rv = convertMiniVariantToVariant(methodInfo, params, - &fullParam, ¶mCount); - if (NS_FAILED(rv)) - return rv; - - bool callDirectly = false; - if (GetProxyType() & NS_PROXY_SYNC && - NS_SUCCEEDED(GetTarget()->IsOnCurrentThread(&callDirectly)) && - callDirectly) { - - // invoke directly using xptc - rv = NS_InvokeByIndex(mRealInterface, methodIndex, - paramCount, fullParam); - - if (fullParam) - free(fullParam); - - return rv; - } - - nsRefPtr<nsProxyObjectCallInfo> proxyInfo = - new nsProxyObjectCallInfo(this, methodInfo, methodIndex, - fullParam, paramCount); - if (!proxyInfo) - return NS_ERROR_OUT_OF_MEMORY; - - if (! (GetProxyType() & NS_PROXY_SYNC)) { - return GetTarget()->Dispatch(proxyInfo, NS_DISPATCH_NORMAL); - } - - // Post synchronously - - nsIThread *thread = NS_GetCurrentThread(); - nsCOMPtr<nsIThreadInternal> threadInt = do_QueryInterface(thread); - NS_ENSURE_STATE(threadInt); - - // Install thread filter to limit event processing only to - // nsProxyObjectCallInfo instances. XXX Add support for sequencing? - nsRefPtr<nsProxyThreadFilter> filter = new nsProxyThreadFilter(); - if (!filter) - return NS_ERROR_OUT_OF_MEMORY; - threadInt->PushEventQueue(filter); - - proxyInfo->SetCallersTarget(thread); - - // Dispatch can fail if the thread is shutting down - rv = GetTarget()->Dispatch(proxyInfo, NS_DISPATCH_NORMAL); - if (NS_SUCCEEDED(rv)) { - while (!proxyInfo->GetCompleted()) { - if (!NS_ProcessNextEvent(thread)) { - rv = NS_ERROR_UNEXPECTED; - break; - } - } - rv = proxyInfo->GetResult(); - } else { - NS_WARNING("Failed to dispatch nsProxyCallEvent"); - } - - threadInt->PopEventQueue(); - - PROXY_LOG(("PROXY(%p): PostAndWait exit [%p %x]\n", this, proxyInfo.get(), rv)); - return rv; -}
deleted file mode 100644 --- a/xpcom/proxy/src/nsProxyEventPrivate.h +++ /dev/null @@ -1,320 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Pierre Phaneuf <pp@ludusdesign.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsProxyEventPrivate_h__ -#define nsProxyEventPrivate_h__ - -#include "nsISupports.h" -#include "nsIFactory.h" -#include "nsIEventTarget.h" -#include "nsIInterfaceInfo.h" -#include "nsIProxyObjectManager.h" - -#include "nsXPTCUtils.h" - -#include "mozilla/Mutex.h" -#include "nsAutoPtr.h" -#include "nsCOMPtr.h" -#include "nsThreadUtils.h" - -#include "nsClassHashtable.h" -#include "nsHashtable.h" - -#include "prlog.h" - -class nsProxyEventObject; - -/** - * To make types clearer, we distinguish between a canonical nsISupports* and - * a proxied interface pointer which represents an arbitrary interface known - * at runtime. - */ -typedef nsISupports nsISomeInterface; - -#define NS_PROXYOBJECT_CLASS_IID \ -{ 0xeea90d45, 0xb059, 0x11d2, \ - { 0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33 } } - -// This IID is used to filter runnables during synchronous event handling. -// The returned pointer is type nsProxyObjectCallInfo - -#define NS_PROXYEVENT_FILTER_IID \ -{ 0xec373590, 0x9164, 0x11d3, \ -{0x8c, 0x73, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} } - -/** - * An object representing an IID and its associated interfaceinfo. Instances - * of this class are obtained via nsProxyObjectManager::GetClass. - */ -class nsProxyEventClass -{ -public: - nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;} - const nsIID& GetProxiedIID() const {return mIID; } - - nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo); - ~nsProxyEventClass(); - - nsIID mIID; - nsCOMPtr<nsIInterfaceInfo> mInfo; - uint32* mDescriptors; -}; - -/** - * A class which provides the XPCOM identity for a proxied object. - * Instances of this class are obtained from the POM, and are uniquely - * hashed on a proxytype/eventtarget/realobject key. - */ -class nsProxyObject : public nsISupports -{ -public: - NS_DECL_ISUPPORTS - - NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROXYOBJECT_CLASS_IID) - - nsProxyObject(nsIEventTarget *destQueue, PRInt32 proxyType, - nsISupports *realObject); - - nsISupports* GetRealObject() const { return mRealObject; } - nsIEventTarget* GetTarget() const { return mTarget; } - PRInt32 GetProxyType() const { return mProxyType; } - - // these are the equivalents of AddRef/Release, but must be called - // while holding the global POM lock - nsrefcnt LockedAddRef(); - nsrefcnt LockedRelease(); - - // LockedFind should be called holding the POM lock. It will - // temporarily unlock the lock during execution. - nsresult LockedFind(REFNSIID iid, void **aResult); - - void LockedRemove(nsProxyEventObject* aObject); - - friend class nsProxyObjectManager; -private: - ~nsProxyObject(); - - PRInt32 mProxyType; - nsCOMPtr<nsIEventTarget> mTarget; /* event target */ - nsCOMPtr<nsISupports> mRealObject; /* the non-proxy object that this object is proxying - This is a strong ref. */ - nsProxyEventObject *mFirst; - - class nsProxyObjectDestructorEvent : public nsRunnable - { - nsProxyObjectDestructorEvent(nsProxyObject *doomed) : - mDoomed(doomed) - {} - - NS_DECL_NSIRUNNABLE - - friend class nsProxyObject; - private: - nsProxyObject *mDoomed; - }; - - friend class nsProxyObjectDestructorEvent; -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsProxyObject, NS_PROXYOBJECT_CLASS_IID) - -/** - * Object representing a single interface implemented on a proxied object. - * This object is maintained in a singly-linked list from the associated - * "parent" nsProxyObject. - */ -class nsProxyEventObject : protected nsAutoXPTCStub -{ -public: - - NS_DECL_ISUPPORTS - - // call this method and return result - NS_IMETHOD CallMethod(PRUint16 methodIndex, - const XPTMethodDescriptor* info, - nsXPTCMiniVariant* params); - - nsProxyEventClass* GetClass() const { return mClass; } - nsISomeInterface* GetProxiedInterface() const { return mRealInterface; } - nsIEventTarget* GetTarget() const { return mProxyObject->GetTarget(); } - PRInt32 GetProxyType() const { return mProxyObject->GetProxyType(); } - - nsresult convertMiniVariantToVariant(const XPTMethodDescriptor *methodInfo, - nsXPTCMiniVariant *params, - nsXPTCVariant **fullParam, - uint8 *outParamCount); - - nsProxyEventObject(nsProxyObject *aParent, - nsProxyEventClass *aClass, - already_AddRefed<nsISomeInterface> aRealInterface, - nsresult *rv); - - // AddRef, but you must be holding the global POM lock - nsrefcnt LockedAddRef(); - friend class nsProxyObject; - -private: - ~nsProxyEventObject(); - - // Member ordering is important: See note in the destructor. - nsProxyEventClass *mClass; - nsCOMPtr<nsProxyObject> mProxyObject; - nsCOMPtr<nsISomeInterface> mRealInterface; - - // Weak reference, maintained by the parent nsProxyObject - nsProxyEventObject *mNext; -}; - -#define NS_PROXYEVENT_IID \ -{ /* 9a24dc5e-2b42-4a5a-aeca-37b8c8fd8ccd */ \ - 0x9a24dc5e, \ - 0x2b42, \ - 0x4a5a, \ - {0xae, 0xca, 0x37, 0xb8, 0xc8, 0xfd, 0x8c, 0xcd} \ -} - -/** - * A class representing a particular proxied method call. - */ -class nsProxyObjectCallInfo : public nsRunnable -{ -public: - - NS_DECL_NSIRUNNABLE - - NS_IMETHOD QueryInterface(REFNSIID aIID, void **aResult); - - NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_IID) - - nsProxyObjectCallInfo(nsProxyEventObject* owner, - const XPTMethodDescriptor *methodInfo, - PRUint32 methodIndex, - nsXPTCVariant* parameterList, - PRUint32 parameterCount); - - ~nsProxyObjectCallInfo(); - - PRUint32 GetMethodIndex() const { return mMethodIndex; } - nsXPTCVariant* GetParameterList() const { return mParameterList; } - PRUint32 GetParameterCount() const { return mParameterCount; } - nsresult GetResult() const { return mResult; } - - bool GetCompleted(); - void SetCompleted(); - void PostCompleted(); - - void SetResult(nsresult rv) { mResult = rv; } - - nsIEventTarget* GetCallersTarget(); - void SetCallersTarget(nsIEventTarget* target); - bool IsSync() const - { - return !!(mOwner->GetProxyType() & NS_PROXY_SYNC); - } - -private: - - nsresult mResult; /* this is the return result of the called function */ - const XPTMethodDescriptor *mMethodInfo; - PRUint32 mMethodIndex; /* which method to be called? */ - nsXPTCVariant *mParameterList; /* marshalled in parameter buffer */ - PRUint32 mParameterCount; /* number of params */ - PRInt32 mCompleted; /* is true when the method has been called. */ - - nsCOMPtr<nsIEventTarget> mCallersTarget; /* this is the dispatch target that we must post a message back to - when we are done invoking the method (only NS_PROXY_SYNC). */ - - nsRefPtr<nsProxyEventObject> mOwner; /* this is the strong referenced nsProxyObject */ - - void RefCountInInterfacePointers(bool addRef); - void CopyStrings(bool copy); -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsProxyObjectCallInfo, NS_PROXYEVENT_IID) - -//////////////////////////////////////////////////////////////////////////////// -// nsProxyObjectManager -//////////////////////////////////////////////////////////////////////////////// - -class nsProxyObjectManager: public nsIProxyObjectManager -{ - typedef mozilla::Mutex Mutex; - -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIPROXYOBJECTMANAGER - - static nsresult Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); - - nsProxyObjectManager(); - - static nsProxyObjectManager *GetInstance(); - static bool IsManagerShutdown(); - - static void Shutdown(); - - nsresult GetClass(REFNSIID aIID, nsProxyEventClass **aResult); - - void LockedRemove(nsProxyObject* aProxy); - - Mutex& GetLock() { return mProxyCreationLock; } - -#ifdef PR_LOGGING - static PRLogModuleInfo *sLog; -#endif - -private: - ~nsProxyObjectManager(); - - static nsProxyObjectManager* gInstance; - nsHashtable mProxyObjectMap; - nsClassHashtable<nsIDHashKey, nsProxyEventClass> mProxyClassMap; - Mutex mProxyCreationLock; -}; - -#define NS_XPCOMPROXY_CLASSNAME "nsProxyObjectManager" -#define NS_PROXYEVENT_MANAGER_CID \ -{ 0xeea90d41, \ - 0xb059, \ - 0x11d2, \ - {0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33} \ -} - -#define PROXY_LOG(args) PR_LOG(nsProxyObjectManager::sLog, PR_LOG_DEBUG, args) - -#endif // nsProxyEventPrivate_h__
deleted file mode 100644 --- a/xpcom/proxy/src/nsProxyObjectManager.cpp +++ /dev/null @@ -1,351 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Doug Turner <dougt@netscape.com> (Original Author) - * Judson Valeski <valeski@netscape.com> - * Dan Matejka <danm@netscape.com> - * Scott Collins <scc@netscape.com> - * Heikki Toivonen <heiki@citec.fi> - * Patrick Beard <beard@netscape.com> - * Pierre Phaneuf <pp@ludusdesign.com> - * Warren Harris <warren@netscape.com> - * Chris Seawood <cls@seawood.org> - * Chris Waterson <waterson@netscape.com> - * Dan Mosedale <dmose@netscape.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsProxyEventPrivate.h" - -#include "nsIComponentManager.h" -#include "nsIProxyObjectManager.h" -#include "nsIServiceManager.h" -#include "nsIThread.h" - -#include "nsCOMPtr.h" -#include "nsThreadUtils.h" -#include "xptiprivate.h" - -using namespace mozilla; - -#ifdef PR_LOGGING -PRLogModuleInfo *nsProxyObjectManager::sLog = PR_NewLogModule("xpcomproxy"); -#endif - -class nsProxyEventKey : public nsHashKey -{ -public: - nsProxyEventKey(void* rootObjectKey, void* targetKey, PRInt32 proxyType) - : mRootObjectKey(rootObjectKey), mTargetKey(targetKey), mProxyType(proxyType) { - } - - PRUint32 HashCode(void) const { - return NS_PTR_TO_INT32(mRootObjectKey) ^ - NS_PTR_TO_INT32(mTargetKey) ^ mProxyType; - } - - bool Equals(const nsHashKey *aKey) const { - const nsProxyEventKey* other = (const nsProxyEventKey*)aKey; - return mRootObjectKey == other->mRootObjectKey - && mTargetKey == other->mTargetKey - && mProxyType == other->mProxyType; - } - - nsHashKey *Clone() const { - return new nsProxyEventKey(mRootObjectKey, mTargetKey, mProxyType); - } - -protected: - void* mRootObjectKey; - void* mTargetKey; - PRInt32 mProxyType; -}; - -///////////////////////////////////////////////////////////////////////// -// nsProxyObjectManager -///////////////////////////////////////////////////////////////////////// - -nsProxyObjectManager* nsProxyObjectManager::gInstance = nsnull; - -NS_IMPL_QUERY_INTERFACE1(nsProxyObjectManager, nsIProxyObjectManager) - -NS_IMETHODIMP_(nsrefcnt) -nsProxyObjectManager::AddRef() -{ - return 2; -} - -NS_IMETHODIMP_(nsrefcnt) -nsProxyObjectManager::Release() -{ - return 1; -} - -nsProxyObjectManager::nsProxyObjectManager() - : mProxyObjectMap(256, false) - , mProxyCreationLock("nsProxyObjectManager.mProxyCreationLock") -{ - mProxyClassMap.Init(256); -} - -nsProxyObjectManager::~nsProxyObjectManager() -{ - mProxyClassMap.Clear(); - - nsProxyObjectManager::gInstance = nsnull; -} - -bool -nsProxyObjectManager::IsManagerShutdown() -{ - return gInstance == nsnull; -} - -nsProxyObjectManager * -nsProxyObjectManager::GetInstance() -{ - if (!gInstance) - gInstance = new nsProxyObjectManager(); - return gInstance; -} - -void -nsProxyObjectManager::Shutdown() -{ - delete gInstance; - NS_ASSERTION(!gInstance, "Destructor didn't null gInstance?"); -} - -nsresult -nsProxyObjectManager::Create(nsISupports* outer, const nsIID& aIID, - void* *aInstancePtr) -{ - nsProxyObjectManager *proxyObjectManager = GetInstance(); - if (!proxyObjectManager) - return NS_ERROR_OUT_OF_MEMORY; - - return proxyObjectManager->QueryInterface(aIID, aInstancePtr); -} - -class nsProxyLockedRefPtr -{ -public: - nsProxyLockedRefPtr(nsProxyObject* aPtr) : - mProxyObject(aPtr) - { - if (mProxyObject) - mProxyObject->LockedAddRef(); - } - - ~nsProxyLockedRefPtr() - { - if (mProxyObject) - mProxyObject->LockedRelease(); - } - - operator nsProxyObject*() const - { - return mProxyObject; - } - - nsProxyObject* operator->() const - { - return mProxyObject; - } - -private: - nsProxyObject *mProxyObject; -}; - -NS_IMETHODIMP -nsProxyObjectManager::GetProxyForObject(nsIEventTarget* aTarget, - REFNSIID aIID, - nsISupports* aObj, - PRInt32 proxyType, - void** aProxyObject) -{ - NS_ENSURE_ARG_POINTER(aObj); - - *aProxyObject = nsnull; - - // handle special values - nsCOMPtr<nsIThread> thread; - if (aTarget == NS_PROXY_TO_CURRENT_THREAD) { - aTarget = NS_GetCurrentThread(); - } else if (aTarget == NS_PROXY_TO_MAIN_THREAD) { - thread = do_GetMainThread(); - aTarget = thread.get(); - } - - // check to see if the target is on our thread. If so, just return the - // real object. - - if (!(proxyType & NS_PROXY_ASYNC) && !(proxyType & NS_PROXY_ALWAYS)) - { - bool result; - aTarget->IsOnCurrentThread(&result); - - if (result) - return aObj->QueryInterface(aIID, aProxyObject); - } - - nsCOMPtr<nsISupports> realObj = do_QueryInterface(aObj); - - // Make sure the object passed in is not a proxy; if it is, be nice and - // build the proxy for the real object. - nsCOMPtr<nsProxyObject> po = do_QueryInterface(aObj); - if (po) { - realObj = po->GetRealObject(); - } - - nsCOMPtr<nsISupports> realEQ = do_QueryInterface(aTarget); - - nsProxyEventKey rootKey(realObj, realEQ, proxyType); - - { - MutexAutoLock lock(mProxyCreationLock); - nsProxyLockedRefPtr root = - (nsProxyObject*) mProxyObjectMap.Get(&rootKey); - if (root) - return root->LockedFind(aIID, aProxyObject); - } - - // don't lock while creating the nsProxyObject - nsProxyObject *newRoot = new nsProxyObject(aTarget, proxyType, realObj); - if (!newRoot) - return NS_ERROR_OUT_OF_MEMORY; - - // lock again, and check for a race putting into mProxyObjectMap - { - MutexAutoLock lock(mProxyCreationLock); - nsProxyLockedRefPtr root = - (nsProxyObject*) mProxyObjectMap.Get(&rootKey); - if (root) { - delete newRoot; - return root->LockedFind(aIID, aProxyObject); - } - - mProxyObjectMap.Put(&rootKey, newRoot); - - nsProxyLockedRefPtr kungFuDeathGrip(newRoot); - return newRoot->LockedFind(aIID, aProxyObject); - } -} - -void -nsProxyObjectManager::LockedRemove(nsProxyObject *aProxy) -{ - nsCOMPtr<nsISupports> realEQ = do_QueryInterface(aProxy->GetTarget()); - - nsProxyEventKey rootKey(aProxy->GetRealObject(), realEQ, aProxy->GetProxyType()); - - if (!mProxyObjectMap.Remove(&rootKey)) { - NS_ERROR("nsProxyObject not found in global hash."); - } -} - -nsresult -nsProxyObjectManager::GetClass(REFNSIID aIID, nsProxyEventClass **aResult) -{ - { - MutexAutoLock lock(mProxyCreationLock); - if (mProxyClassMap.Get(aIID, aResult)) { - NS_ASSERTION(*aResult, "Null data in mProxyClassMap"); - return NS_OK; - } - } - - nsIInterfaceInfoManager *iim = - xptiInterfaceInfoManager::GetSingleton(); - if (!iim) - return NS_ERROR_FAILURE; - - nsCOMPtr<nsIInterfaceInfo> ii; - nsresult rv = iim->GetInfoForIID(&aIID, getter_AddRefs(ii)); - if (NS_FAILED(rv)) - return rv; - - nsProxyEventClass *pec = new nsProxyEventClass(aIID, ii); - if (!pec) - return NS_ERROR_OUT_OF_MEMORY; - - // Re-lock to put this class into our map. Before putting, check to see - // if another thread raced to put before us - MutexAutoLock lock(mProxyCreationLock); - - if (mProxyClassMap.Get(aIID, aResult)) { - NS_ASSERTION(*aResult, "Null data in mProxyClassMap"); - delete pec; - return NS_OK; - } - - if (!mProxyClassMap.Put(aIID, pec)) { - delete pec; - return NS_ERROR_OUT_OF_MEMORY; - } - - *aResult = pec; - return NS_OK; -} - -/** - * Helper function for code that already has a link-time dependency on - * libxpcom and needs to get proxies in a bunch of different places. - * This way, the caller isn't forced to get the proxy object manager - * themselves every single time, thus making the calling code more - * readable. - */ -nsresult -NS_GetProxyForObject(nsIEventTarget *target, - REFNSIID aIID, - nsISupports* aObj, - PRInt32 proxyType, - void** aProxyObject) -{ - static NS_DEFINE_CID(proxyObjMgrCID, NS_PROXYEVENT_MANAGER_CID); - - nsresult rv; - - // get the proxy object manager - // - nsCOMPtr<nsIProxyObjectManager> proxyObjMgr = - do_GetService(proxyObjMgrCID, &rv); - if (NS_FAILED(rv)) - return rv; - - // and try to get the proxy object - // - return proxyObjMgr->GetProxyForObject(target, aIID, aObj, - proxyType, aProxyObject); -}
deleted file mode 100644 --- a/xpcom/proxy/tests/Makefile.in +++ /dev/null @@ -1,62 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = xpcom_tests -XPIDL_MODULE = proxytest - -CPPSRCS = proxytests.cpp \ - proxy-create-threadsafety.cpp \ - $(NULL) -XPIDLSRCS = nsITestProxy.idl - -SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX)) - -LIBS = \ - $(DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \ - $(XPCOM_LIBS) \ - $(NSPR_LIBS) \ - $(MOZ_JS_LIBS) \ - $(NULL) - -include $(topsrcdir)/config/rules.mk
deleted file mode 100644 --- a/xpcom/proxy/tests/nsITestProxy.idl +++ /dev/null @@ -1,9 +0,0 @@ -#include "nsISupports.idl" - -[uuid(1979e980-1cfd-11d3-915e-0000863011c4)] -interface nsITestProxy : nsISupports -{ - long Test(in long p1, in long p2); - void Test2(); - void Test3(in nsISupports p1, out nsISupports p2); -};
deleted file mode 100644 --- a/xpcom/proxy/tests/proxy-create-threadsafety.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Mark 'Mook' Yen <mook@songbirdnest.com> - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include <stdio.h> - -#include "nsXPCOM.h" -#include "nsXPCOMCIDInternal.h" -#include "nsIComponentManager.h" -#include "nsIComponentRegistrar.h" -#include "nsIServiceManager.h" -#include "nsAutoPtr.h" -#include "nsCOMPtr.h" - -#include "nscore.h" -#include "nspr.h" - -#include "nsITestProxy.h" -#include "nsISupportsPrimitives.h" - -#include "mozilla/ReentrantMonitor.h" -#include "mozilla/Mutex.h" -#include "nsIRunnable.h" -#include "nsIProxyObjectManager.h" -#include "nsXPCOMCIDInternal.h" -#include "nsComponentManagerUtils.h" -#include "nsServiceManagerUtils.h" -#include "nsThreadUtils.h" -#include "nsISupportsUtils.h" - -using namespace mozilla; - -/* - -A quick diagram of how this test works: - -This tests for bug 400450, where the creation of a proxy event object -causes a deadlock. We use a counter and a monitor to make things -be more deterministic. - -The leftmost column marks the thread that is running. - -M Create two threads -1 Get a proxy -1 proxy event object created -1 (Proxy object QIs the target) -1 Lock [*] -2 Get a proxy -2 proxy event object created -2 (Proxy object calls QI) -2 Unlock [*] -2 proxy event object stored -2 proxy obtained -1 proxy event object released - - - */ - -/***************************************************************************/ -/* ProxyTest */ -/***************************************************************************/ - -class ProxyTest : public nsIRunnable, - public nsITestProxy, - public nsISupportsPrimitive -{ -public: - ProxyTest() - : mCounterLock("ProxyTest.mCounterLock") - , mEvilReentrantMonitor("ProxyTest.mEvilReentrantMonitor") - , mCounter(0) - {} - - NS_IMETHOD Run() - { - nsresult rv; - nsCOMPtr<nsIProxyObjectManager> pom = - do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr<nsISupportsPrimitive> prim; - rv = pom->GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, - NS_GET_IID(nsISupportsPrimitive), - NS_ISUPPORTS_CAST(nsIRunnable*, this), - NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(prim)); - NS_ENSURE_SUCCESS(rv, rv); - /* we don't actually need to use the proxied object */ - return NS_OK; - } - - NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32 *_retval) - { - nsresult rv; - - if (!NS_IsMainThread()) - return NS_ERROR_UNEXPECTED; - - /* note that we don't have an event queue... */ - - rv = NS_NewThread(getter_AddRefs(mThreadOne), - static_cast<nsIRunnable*>(this)); - NS_ENSURE_SUCCESS(rv, rv); - rv = NS_NewThread(getter_AddRefs(mThreadTwo), - static_cast<nsIRunnable*>(this)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = mThreadOne->Shutdown(); - NS_ENSURE_SUCCESS(rv, rv); - rv = mThreadTwo->Shutdown(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; - } - - NS_IMETHOD Test2(void) - { - return NS_ERROR_NOT_IMPLEMENTED; - } - - NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2) - { - return NS_ERROR_NOT_IMPLEMENTED; - } - - NS_IMETHOD GetType(PRUint16 *_retval) - { - return NS_ERROR_NOT_IMPLEMENTED; - } - - NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) - { - NS_ASSERTION(aInstancePtr, - "QueryInterface requires a non-NULL destination!"); - nsISupports* foundInterface; - if ( aIID.Equals(NS_GET_IID(nsIRunnable)) ) { - foundInterface = static_cast<nsIRunnable*>(this); - } else if ( aIID.Equals(NS_GET_IID(nsITestProxy)) ) { - foundInterface = static_cast<nsITestProxy*>(this); - } else if ( aIID.Equals(NS_GET_IID(nsISupports)) ) { - foundInterface = NS_ISUPPORTS_CAST(nsIRunnable*, this); - } else if ( aIID.Equals(NS_GET_IID(nsISupportsPrimitive)) ) { - { - MutexAutoLock counterLock(mCounterLock); - switch(mCounter) { - case 0: - ++mCounter; - { - /* be evil here and hang */ - MutexAutoUnlock counterUnlock(mCounterLock); - ReentrantMonitorAutoEnter evilReentrantMonitor(mEvilReentrantMonitor); - nsresult rv = evilReentrantMonitor.Wait(); - NS_ENSURE_SUCCESS(rv, rv); - break; - } - case 1: - ++mCounter; - { - /* okay, we had our fun, un-hang */ - MutexAutoUnlock counterUnlock(mCounterLock); - ReentrantMonitorAutoEnter evilReentrantMonitor(mEvilReentrantMonitor); - nsresult rv = evilReentrantMonitor.Notify(); - NS_ENSURE_SUCCESS(rv, rv); - break; - } - default: { - /* nothing special here */ - ++mCounter; - } - } - ++mCounter; - } - // remeber to admit to supporting this interface - foundInterface = static_cast<nsISupportsPrimitive*>(this); - } else { - foundInterface = nsnull; - } - nsresult status; - if (!foundInterface) { - status = NS_ERROR_NO_INTERFACE; - } else { - NS_ADDREF(foundInterface); - status = NS_OK; - } - *aInstancePtr = foundInterface; - return status; - } - - NS_IMETHOD_(nsrefcnt) AddRef(void); - NS_IMETHOD_(nsrefcnt) Release(void); - -protected: - nsAutoRefCnt mRefCnt; - NS_DECL_OWNINGTHREAD - -private: - Mutex mCounterLock; - ReentrantMonitor mEvilReentrantMonitor; - PRInt32 mCounter; - nsCOMPtr<nsIThread> mThreadOne; - nsCOMPtr<nsIThread> mThreadTwo; -}; - -NS_IMPL_THREADSAFE_ADDREF(ProxyTest) -NS_IMPL_THREADSAFE_RELEASE(ProxyTest) - -int -main(int argc, char **argv) -{ - NS_InitXPCOM2(nsnull, nsnull, nsnull); - - // Scope code so everything is destroyed before we run call NS_ShutdownXPCOM - { - nsCOMPtr<nsITestProxy> tester = new ProxyTest(); - tester->Test(0, 0, nsnull); - } - - NS_ShutdownXPCOM(nsnull); - - return 0; -} -
deleted file mode 100644 --- a/xpcom/proxy/tests/proxytests.cpp +++ /dev/null @@ -1,554 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Pierre Phaneuf <pp@ludusdesign.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include <stdio.h> - -#include "nsXPCOM.h" -#include "nsXPCOMCIDInternal.h" -#include "nsIComponentManager.h" -#include "nsIComponentRegistrar.h" -#include "nsIServiceManager.h" -#include "nsAutoPtr.h" -#include "nsCOMPtr.h" -#include "nsCOMArray.h" - -#include "nscore.h" -#include "nspr.h" -#include "prmon.h" - -#include "nsITestProxy.h" - -#include "nsIRunnable.h" -#include "nsIProxyObjectManager.h" -#include "nsIThreadPool.h" -#include "nsXPCOMCIDInternal.h" -#include "nsComponentManagerUtils.h" -#include "nsServiceManagerUtils.h" -#include "nsThreadUtils.h" - -#include "prlog.h" -#ifdef PR_LOGGING -static PRLogModuleInfo *sLog = PR_NewLogModule("Test"); -#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args) -#else -#define LOG(args) printf args -#endif - -namespace proxytests { - -static nsresult -GetThreadFromPRThread(PRThread *prthread, nsIThread **result) -{ - LOG(("TEST: GetThreadFromPRThread [%p]\n", prthread)); - - nsCOMPtr<nsIThreadManager> tm = do_GetService(NS_THREADMANAGER_CONTRACTID); - NS_ENSURE_STATE(tm); - return tm->GetThreadFromPRThread(prthread, result); -} - -/***************************************************************************/ -/* nsTestXPCFoo */ -/***************************************************************************/ -class nsTestXPCFoo : public nsITestProxy -{ - NS_DECL_ISUPPORTS - NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval); - NS_IMETHOD Test2(); - NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2); - - nsTestXPCFoo(); -}; - -nsTestXPCFoo::nsTestXPCFoo() -{ - NS_ADDREF_THIS(); -} - -NS_IMPL_ISUPPORTS1(nsTestXPCFoo, nsITestProxy) - -NS_IMETHODIMP nsTestXPCFoo::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval) -{ - LOG(("TEST: Thread (%d) Test Called successfully! Party on...\n", p1)); - *retval = p1+p2; - return NS_OK; -} - - -NS_IMETHODIMP nsTestXPCFoo::Test2() -{ - LOG(("TEST: The quick brown netscape jumped over the old lazy ie..\n")); - - return NS_OK; -} - -NS_IMETHODIMP nsTestXPCFoo::Test3(nsISupports *p1, nsISupports **p2) -{ - if (p1 != nsnull) - { - nsITestProxy *test; - - p1->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test); - - test->Test2(); - PRInt32 a; - test->Test( 1, 2, &a); - LOG(("TEST: \n1+2=%d\n",a)); - } - - - *p2 = new nsTestXPCFoo(); - return NS_OK; -} - -/***************************************************************************/ -/* nsTestXPCFoo2 */ -/***************************************************************************/ -class nsTestXPCFoo2 : public nsITestProxy -{ - NS_DECL_ISUPPORTS - NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval); - NS_IMETHOD Test2(); - NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2); - - nsTestXPCFoo2(); -}; - -nsTestXPCFoo2::nsTestXPCFoo2() -{ - NS_ADDREF_THIS(); -} - -NS_IMPL_THREADSAFE_ISUPPORTS1(nsTestXPCFoo2, nsITestProxy) - -NS_IMETHODIMP nsTestXPCFoo2::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval) -{ - LOG(("TEST: calling back to caller!\n")); - - nsCOMPtr<nsIProxyObjectManager> manager = - do_GetService(NS_XPCOMPROXY_CONTRACTID); - - LOG(("TEST: ProxyObjectManager: %p \n", (void *) manager.get())); - - PR_ASSERT(manager); - - nsCOMPtr<nsIThread> thread; - GetThreadFromPRThread((PRThread *) p1, getter_AddRefs(thread)); - NS_ENSURE_STATE(thread); - - nsCOMPtr<nsITestProxy> proxyObject; - manager->GetProxyForObject(thread, NS_GET_IID(nsITestProxy), this, NS_PROXY_SYNC, (void**)&proxyObject); - proxyObject->Test3(nsnull, nsnull); - - LOG(("TEST: Deleting Proxy Object\n")); - return NS_OK; -} - - -NS_IMETHODIMP nsTestXPCFoo2::Test2() -{ - LOG(("TEST: nsTestXPCFoo2::Test2() called\n")); - - return NS_OK; -} - - -NS_IMETHODIMP nsTestXPCFoo2::Test3(nsISupports *p1, nsISupports **p2) -{ - LOG(("TEST: Got called")); - return NS_OK; -} - - - -#if 0 -struct ArgsStruct { - nsIThread* thread; - PRInt32 threadNumber; -}; - - - -// This will create two objects both descendants of a single IID. -void TestCase_TwoClassesOneInterface(void *arg) -{ - ArgsStruct *argsStruct = (ArgsStruct*) arg; - - - nsCOMPtr<nsIProxyObjectManager> manager = - do_GetService(NS_XPCOMPROXY_CONTRACTID); - - printf("ProxyObjectManager: %p \n", (void *) manager.get()); - - PR_ASSERT(manager); - - nsITestProxy *proxyObject; - nsITestProxy *proxyObject2; - - nsTestXPCFoo* foo = new nsTestXPCFoo(); - nsTestXPCFoo2* foo2 = new nsTestXPCFoo2(); - - PR_ASSERT(foo); - PR_ASSERT(foo2); - - - manager->GetProxyForObject(argsStruct->thread, NS_GET_IID(nsITestProxy), foo, NS_PROXY_SYNC, (void**)&proxyObject); - - manager->GetProxyForObject(argsStruct->thread, NS_GET_IID(nsITestProxy), foo2, NS_PROXY_SYNC, (void**)&proxyObject2); - - - - if (proxyObject && proxyObject2) - { - // release ownership of the real object. - - PRInt32 a; - nsresult rv; - PRInt32 threadNumber = argsStruct->threadNumber; - - printf("Deleting real Object (%d)\n", threadNumber); - NS_RELEASE(foo); - - printf("Deleting real Object 2 (%d)\n", threadNumber); - NS_RELEASE(foo2); - - - printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber); - rv = proxyObject->Test(threadNumber, 0, &a); - printf("Thread (%d) error: %d.\n", threadNumber, rv); - - - printf("Thread (%d) Prior to calling proxyObject->Test2.\n", threadNumber); - rv = proxyObject->Test2(); - printf("Thread (%d) error: %d.\n", threadNumber, rv); - - printf("Thread (%d) Prior to calling proxyObject2->Test2.\n", threadNumber); - rv = proxyObject2->Test2(); - printf("Thread (%d) proxyObject2 error: %d.\n", threadNumber, rv); - - printf("Deleting Proxy Object (%d)\n", threadNumber ); - NS_RELEASE(proxyObject); - - printf("Deleting Proxy Object 2 (%d)\n", threadNumber ); - NS_RELEASE(proxyObject2); - } - - PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters -} -#endif - - - -void TestCase_NestedLoop(nsIThread *thread, PRInt32 index) -{ - nsCOMPtr<nsIProxyObjectManager> manager = - do_GetService(NS_XPCOMPROXY_CONTRACTID); - - LOG(("TEST: ProxyObjectManager: %p\n", (void *) manager.get())); - - PR_ASSERT(manager); - - nsITestProxy *proxyObject; - nsTestXPCFoo2* foo = new nsTestXPCFoo2(); - - PR_ASSERT(foo); - - - manager->GetProxyForObject(thread, NS_GET_IID(nsITestProxy), foo, NS_PROXY_SYNC, (void**)&proxyObject); - - if (proxyObject) - { - // release ownership of the real object. - - nsresult rv; - - LOG(("TEST: Deleting real Object (%d)\n", index)); - NS_RELEASE(foo); - - PRInt32 retval; - - LOG(("TEST: Getting EventThread...\n")); - - //nsCOMPtr<nsIThread> curThread = do_GetCurrentThread(); - PRThread *curThread = PR_GetCurrentThread(); - if (curThread) - { - LOG(("TEST: Thread (%d) Prior to calling proxyObject->Test.\n", index)); - rv = proxyObject->Test(NS_PTR_TO_INT32((void*)curThread), 0, &retval); // XXX broken on 64-bit arch - LOG(("TEST: Thread (%d) proxyObject error: %x.\n", index, rv)); - - LOG(("TEST: Deleting Proxy Object (%d)\n", index)); - NS_RELEASE(proxyObject); - } - - PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters - } -} - - -#if 0 -void TestCase_nsISupports(void *arg) -{ - - ArgsStruct *argsStruct = (ArgsStruct*) arg; - - nsCOMPtr<nsIProxyObjectManager> manager = - do_GetService(NS_XPCOMPROXY_CONTRACTID); - - PR_ASSERT(manager); - - nsITestProxy *proxyObject; - nsTestXPCFoo* foo = new nsTestXPCFoo(); - - PR_ASSERT(foo); - - manager->GetProxyForObject(argsStruct->thread, NS_GET_IID(nsITestProxy), foo, NS_PROXY_SYNC, (void**)&proxyObject); - - if (proxyObject != nsnull) - { - nsISupports *bISupports = nsnull, *cISupports = nsnull; - - proxyObject->Test3(foo, &bISupports); - proxyObject->Test3(bISupports, &cISupports); - - nsITestProxy *test; - bISupports->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test); - - test->Test2(); - - NS_RELEASE(foo); - NS_RELEASE(proxyObject); - } -} -#endif - -/***************************************************************************/ -/* ProxyTest */ -/***************************************************************************/ - -class ProxyTest : public nsIRunnable -{ -public: - NS_DECL_ISUPPORTS - - ProxyTest(PRThread *eventLoopThread, PRInt32 index) - : mEventLoopThread(eventLoopThread) - , mIndex(index) - {} - - NS_IMETHOD Run() - { - //TestCase_TwoClassesOneInterface(arg); - //TestCase_nsISupports(arg); - nsCOMPtr<nsIThread> thread; - GetThreadFromPRThread(mEventLoopThread, getter_AddRefs(thread)); - TestCase_NestedLoop(thread, mIndex); - - return NS_OK; - } - -private: - PRThread *mEventLoopThread; - PRInt32 mIndex; -}; -NS_IMPL_THREADSAFE_ISUPPORTS1(ProxyTest, nsIRunnable) - -class TestSyncProxyToSelf : public nsIRunnable -{ -public: - NS_DECL_ISUPPORTS - - NS_IMETHOD Run() - { - LOG(("TEST: Verifing calling Proxy on eventQ thread.\n")); - - nsCOMPtr<nsIThread> thread = do_GetCurrentThread(); - - nsITestProxy *proxyObject; - nsTestXPCFoo *foo = new nsTestXPCFoo(); - NS_ENSURE_STATE(foo); - - nsCOMPtr<nsIProxyObjectManager> manager = - do_GetService(NS_XPCOMPROXY_CONTRACTID); - - manager->GetProxyForObject(thread, - NS_GET_IID(nsITestProxy), foo, - NS_PROXY_SYNC, (void**)&proxyObject); - - PRInt32 a; - proxyObject->Test(1, 2, &a); - proxyObject->Test2(); - - NS_RELEASE(proxyObject); - delete foo; - - LOG(("TEST: End of Verification calling Proxy on eventQ thread.\n")); - - return NS_OK; - } -}; -NS_IMPL_THREADSAFE_ISUPPORTS1(TestSyncProxyToSelf, nsIRunnable) - -//--------------------------------------------------------------------------- -// Test to make sure we can call methods on a "main thread only" object from -// a background thread. - -class MainThreadOnly : public nsIRunnable { -public: - NS_DECL_ISUPPORTS - NS_IMETHOD Run() { - NS_ASSERTION(NS_IsMainThread(), "method called on wrong thread"); - *mNumRuns -= 1; - return NS_OK; - } - MainThreadOnly(PRUint32 *numRuns) : mNumRuns(numRuns) {} - ~MainThreadOnly() { - NS_ASSERTION(NS_IsMainThread(), "method called on wrong thread"); - } - bool IsDone() { return mNumRuns == 0; } -private: - PRUint32 *mNumRuns; -}; -NS_IMPL_ISUPPORTS1(MainThreadOnly, nsIRunnable) // not threadsafe! - -static nsresult -RunApartmentTest() -{ - LOG(("RunApartmentTest: start\n")); - - const PRUint32 numDispatched = 160; - - PRUint32 numCompleted = 0; - nsCOMPtr<nsIRunnable> obj = new MainThreadOnly(&numCompleted); - - nsCOMPtr<nsIProxyObjectManager> manager = - do_GetService(NS_XPCOMPROXY_CONTRACTID); - - nsCOMPtr<nsIRunnable> objProxy; - manager->GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, - NS_GET_IID(nsIRunnable), - obj, - NS_PROXY_ASYNC, - getter_AddRefs(objProxy)); - nsCOMPtr<nsIThread> thread; - NS_NewThread(getter_AddRefs(thread)); - - obj = nsnull; - - nsCOMPtr<nsIThreadPool> pool = do_CreateInstance(NS_THREADPOOL_CONTRACTID); - - pool->SetThreadLimit(8); - for (PRUint32 i = 0; i < numDispatched; ++i) - pool->Dispatch(objProxy, NS_DISPATCH_NORMAL); - - objProxy = nsnull; - - nsCOMPtr<nsIThread> curThread = do_GetCurrentThread(); - while (numCompleted < numDispatched) { - NS_ProcessNextEvent(curThread); - } - - pool->Shutdown(); - - LOG(("RunApartmentTest: end\n")); - return NS_OK; -} - -} // namespace - -using namespace proxytests; - -int -main(int argc, char **argv) -{ - int numberOfThreads = 1; - - if (argc > 1) - numberOfThreads = atoi(argv[1]); - - NS_InitXPCOM2(nsnull, nsnull, nsnull); - - // Scope code so everything is destroyed before we run call NS_ShutdownXPCOM - { - RunApartmentTest(); - - nsCOMPtr<nsIThread> eventLoopThread; - NS_NewThread(getter_AddRefs(eventLoopThread)); - - nsCOMPtr<nsIRunnable> test = new TestSyncProxyToSelf(); - eventLoopThread->Dispatch(test, NS_DISPATCH_NORMAL); - - PRThread *eventLoopPRThread; - eventLoopThread->GetPRThread(&eventLoopPRThread); - PR_ASSERT(eventLoopPRThread); - - LOG(("TEST: Spawn Threads:\n")); - nsCOMArray<nsIThread> threads; - for (PRInt32 spawn = 0; spawn < numberOfThreads; spawn++) - { - test = new ProxyTest(eventLoopPRThread, spawn); - - nsCOMPtr<nsIThread> thread; - NS_NewThread(getter_AddRefs(thread), test); - - threads.AppendObject(thread); - - LOG(("TEST: \tThread (%d) spawned\n", spawn)); - - PR_Sleep( PR_MillisecondsToInterval(250) ); - } - - LOG(("TEST: All Threads Spawned.\n")); - - LOG(("TEST: Wait for threads.\n")); - for (PRInt32 i = 0; i < numberOfThreads; i++) - { - LOG(("TEST: Thread (%d) Join...\n", i)); - nsresult rv = threads[i]->Shutdown(); - LOG(("TEST: Thread (%d) Joined. (error: %x).\n", i, rv)); - } - - LOG(("TEST: Shutting down event loop thread\n")); - eventLoopThread->Shutdown(); - } - - LOG(("TEST: Calling Cleanup.\n")); - NS_ShutdownXPCOM(nsnull); - - LOG(("TEST: Return zero.\n")); - return 0; -}
--- a/xpcom/tests/Makefile.in +++ b/xpcom/tests/Makefile.in @@ -109,17 +109,16 @@ endif #CPP_UNIT_TESTS += \ # TestArray.cpp \ # TestCRT.cpp \ # TestDeque.cpp \ # TestEncoding.cpp \ # TestExpirationTracker.cpp \ # TestPipes.cpp \ # TestPriorityQueue.cpp \ -# TestProxies.cpp \ # TestStorageStream.cpp \ # TestStrings.cpp \ # TestSynchronization.cpp \ # TestTArray.cpp \ # TestThreadPool.cpp \ # TestThreads.cpp \ # TestTimeStamp.cpp \ # TestXPIDLString.cpp \
deleted file mode 100644 --- a/xpcom/tests/TestProxies.cpp +++ /dev/null @@ -1,798 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Proxy Test Code. - * - * The Initial Developer of the Original Code is - * Ben Turner <bent.mozilla@gmail.com>. - * Portions created by the Initial Developer are Copyright (C) 2008 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "TestHarness.h" - -#include "nsIEventTarget.h" -#include "nsIProxyObjectManager.h" -#include "nsIRunnable.h" -#include "nsIThread.h" -#include "nsIThreadPool.h" - -#include "nsAutoPtr.h" -#include "nsCOMPtr.h" -#include "nsComponentManagerUtils.h" -#include "nsServiceManagerUtils.h" -#include "nsThreadUtils.h" -#include "nsXPCOMCIDInternal.h" -#include "prlog.h" - -#include "mozilla/Mutex.h" -using namespace mozilla; - -typedef nsresult(*TestFuncPtr)(); - -#define TEST_NAME "TestProxies" - -#ifdef PR_LOGGING -static PRLogModuleInfo* sLog = PR_NewLogModule(TEST_NAME); -#endif -#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args) - -static nsIThread* gMainThread = nsnull; -static nsIThread* gTestThread = nsnull; - -static nsresult -GetProxyForObject(nsIEventTarget* aTarget, - REFNSIID aIID, - nsISupports* aObj, - PRInt32 aProxyType, - void** aProxyObject) -{ - nsresult rv; - nsCOMPtr<nsIProxyObjectManager> proxyObjMgr = - do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - return proxyObjMgr->GetProxyForObject(aTarget, aIID, aObj, aProxyType, - aProxyObject); -} - -class nsAutoTestThread -{ -public: - nsAutoTestThread(nsIThread** aGlobal = nsnull) - : mGlobal(aGlobal) - { - nsCOMPtr<nsIThread> newThread; - nsresult rv = NS_NewThread(getter_AddRefs(newThread)); - if (NS_FAILED(rv)) - return; - - rv = newThread->GetPRThread(&mNativeThread); - if (NS_FAILED(rv)) - return; - - LOG(("Created test thread [0x%p]", static_cast<void*>(mNativeThread))); - - newThread.swap(mThread); - - if (mGlobal) - *mGlobal = mThread; - } - - ~nsAutoTestThread() - { - if (mGlobal) - *mGlobal = nsnull; - -#ifdef PR_LOGGING - void* nativeThread = static_cast<void*>(mNativeThread); -#endif - - LOG(("Shutting down test thread [0x%p]", nativeThread)); - mThread->Shutdown(); - LOG(("Test thread successfully shut down [0x%p]", nativeThread)); - } - - operator nsIThread*() const - { - return mThread; - } - - nsIThread* operator->() const - { - return mThread; - } - -private: - nsIThread** mGlobal; - nsCOMPtr<nsIThread> mThread; - PRThread* mNativeThread; -}; - -class SimpleRunnable : public nsRunnable -{ -public: - SimpleRunnable(const char* aType = "SimpleRunnable") - : mType(aType) - { } - - NS_IMETHOD Run() - { - LOG(("%s::Run() [0x%p]", mType, - static_cast<void*>(static_cast<nsISupports*>(this)))); - return NS_OK; - } -private: - const char* mType; -}; - -class TestTargetThreadRunnable : public SimpleRunnable -{ -public: - TestTargetThreadRunnable(nsIThread* aTarget) - : SimpleRunnable("TestTargetThreadRunnable"), - mTarget(aTarget) - { } - - NS_IMETHOD Run() - { - nsresult rv = SimpleRunnable::Run(); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr<nsIThread> currentThread(do_GetCurrentThread()); - if (currentThread != mTarget) { - NS_ERROR("Proxy sent call to wrong thread!"); - return NS_ERROR_FAILURE; - } - - return NS_OK; - } - -private: - nsCOMPtr<nsIThread> mTarget; -}; - -class ChainedProxyRunnable : public SimpleRunnable -{ -public: - ChainedProxyRunnable(nsIThread* aSecondTarget, - nsIThread* aThirdTarget = nsnull) - : SimpleRunnable("ChainedProxyRunnable"), mSecondTarget(aSecondTarget), - mThirdTarget(aThirdTarget) - { } - - NS_IMETHOD Run() - { - nsresult rv = SimpleRunnable::Run(); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr<SimpleRunnable> runnable = mThirdTarget ? - new ChainedProxyRunnable(mThirdTarget) : - new SimpleRunnable(); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - nsCOMPtr<nsIRunnable> proxy; - rv = GetProxyForObject(mSecondTarget, NS_GET_IID(nsIRunnable), runnable, - NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; - } - -private: - nsCOMPtr<nsIThread> mSecondTarget; - nsCOMPtr<nsIThread> mThirdTarget; -}; - -class IncrementingRunnable : public SimpleRunnable -{ -public: - IncrementingRunnable(PRUint32* aCounter, Mutex* aLock = nsnull) - : SimpleRunnable("IncrementingRunnable"), mCounter(aCounter), mLock(aLock) - { } - - NS_IMETHOD Run() - { - nsresult rv = SimpleRunnable::Run(); - NS_ENSURE_SUCCESS(rv, rv); - - if (mLock) - mLock->Lock(); - - (*mCounter)++; - - if (mLock) - mLock->Unlock(); - - return NS_OK; - } - -private: - PRUint32* mCounter; - Mutex* mLock; -}; - -class NonThreadsafeRunnable : public nsIRunnable -{ -public: - NS_DECL_ISUPPORTS - - NonThreadsafeRunnable(PRUint32* aCounter, - const char* aType = "NonThreadsafeRunnable") - : mCounter(aCounter), - mType(aType) - { } - - virtual ~NonThreadsafeRunnable() - { }; - - NS_IMETHOD Run() - { - LOG(("%s::Run() [0x%p]", mType, - static_cast<void*>(static_cast<nsISupports*>(this)))); - - (*mCounter)++; - return NS_OK; - } - -private: - PRUint32* mCounter; - const char* mType; -}; - -NS_IMPL_ISUPPORTS1(NonThreadsafeRunnable, nsIRunnable) - -class MainThreadRunnable : public NonThreadsafeRunnable -{ -public: - NS_DECL_ISUPPORTS_INHERITED - - MainThreadRunnable(PRUint32* aCounter) - : NonThreadsafeRunnable(aCounter, "MainThreadRunnable") - { - if (!NS_IsMainThread()) { - NS_ERROR("Not running on the main thread!"); - } - } - - virtual ~MainThreadRunnable() - { - if (!NS_IsMainThread()) { - NS_ERROR("Not running on the main thread!"); - } - } - - NS_IMETHOD Run() - { - if (!NS_IsMainThread()) { - NS_ERROR("Not running on the main thread!"); - return NS_ERROR_FAILURE; - } - - nsresult rv = NonThreadsafeRunnable::Run(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; - } -}; - -NS_IMPL_ISUPPORTS_INHERITED0(MainThreadRunnable, NonThreadsafeRunnable) - -class ProxyGetter : public nsRunnable -{ -public: - ProxyGetter(nsIRunnable* aRunnable, nsIRunnable** retval) - : mRunnable(aRunnable), _retval(retval) - { } - - NS_IMETHOD Run() - { - *_retval = nsnull; - - if (NS_IsMainThread()) { - NS_ERROR("Shouldn't be running on the main thread!"); - return NS_ERROR_FAILURE; - } - - nsCOMPtr<nsIRunnable> proxy; - nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), - mRunnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - proxy.forget(_retval); - return NS_OK; - } - -private: - nsIRunnable* mRunnable; - nsIRunnable** _retval; -}; - -class RunnableGetter : public nsRunnable -{ -public: - RunnableGetter(PRUint32* aCounter, nsIRunnable** retval) - : mCounter(aCounter), _retval(retval) - { } - - NS_IMETHOD Run() - { - *_retval = nsnull; - - if (NS_IsMainThread()) { - NS_ERROR("Shouldn't be running on the main thread!"); - return NS_ERROR_FAILURE; - } - - nsCOMPtr<nsIRunnable> runnable = new NonThreadsafeRunnable(mCounter); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - runnable.forget(_retval); - return NS_OK; - } - -private: - PRUint32* mCounter; - nsIRunnable** _retval; -}; - -nsresult -TestTargetThread() -{ - LOG(("--- Running TestTargetThread ---")); - - nsRefPtr<TestTargetThreadRunnable> runnable = - new TestTargetThreadRunnable(gMainThread); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - nsCOMPtr<nsIRunnable> proxy; - nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), - runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - - runnable = new TestTargetThreadRunnable(gTestThread); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable, - NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -nsresult -TestNonThreadsafeProxy() -{ - LOG(("--- Running TestNonThreadsafeProxy 1 ---")); - - // Make sure a non-threadsafe object and proxy to it (both created on the same - // thread) can be used on the same thread. - - PRUint32 counter = 0; - nsCOMPtr<nsIRunnable> runnable(new MainThreadRunnable(&counter)); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - nsCOMPtr<nsIRunnable> proxy; - nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), - runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - for (PRUint32 otherCounter = 0; otherCounter < 5;) { - rv = gTestThread->Dispatch(proxy, NS_DISPATCH_SYNC); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE); - } - - // Make sure a non-threadsafe object and proxy to it (both created on the same - // thread) can be used on a different thread. - - LOG(("--- Running TestNonThreadsafeProxy 2 ---")); - - counter = 0; - runnable = new NonThreadsafeRunnable(&counter); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), - runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - runnable = nsnull; - - for (PRUint32 otherCounter = 0; otherCounter < 5;) { - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE); - } - - NS_ENSURE_TRUE(counter == 5, NS_ERROR_FAILURE); - - // Make sure a non-threadsafe object and proxy to it (created on different - // threads) can be used by any thread. - - LOG(("--- Running TestNonThreadsafeProxy 3 ---")); - - counter = 0; - proxy = nsnull; - - runnable = new MainThreadRunnable(&counter); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - nsCOMPtr<nsIRunnable> proxyGetter = - new ProxyGetter(runnable, getter_AddRefs(proxy)); - NS_ENSURE_TRUE(proxyGetter, NS_ERROR_OUT_OF_MEMORY); - - rv = gTestThread->Dispatch(proxyGetter, NS_DISPATCH_SYNC); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(proxy, NS_ERROR_FAILURE); - - for (PRUint32 otherCounter = 0; otherCounter < 5;) { - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE); - } - - // Make sure a non-threadsafe object (created on thread 1) and proxy to it - // (created on thread 2) can be used by thread 3. - - LOG(("--- Running TestNonThreadsafeProxy 4 ---")); - - counter = 0; - proxy = nsnull; - runnable = nsnull; - - nsCOMPtr<nsIRunnable> runnableGetter = - new RunnableGetter(&counter, getter_AddRefs(runnable)); - NS_ENSURE_TRUE(runnableGetter, NS_ERROR_OUT_OF_MEMORY); - - rv = gTestThread->Dispatch(runnableGetter, NS_DISPATCH_SYNC); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(runnable, NS_ERROR_FAILURE); - - proxyGetter = new ProxyGetter(runnable, getter_AddRefs(proxy)); - NS_ENSURE_TRUE(proxyGetter, NS_ERROR_OUT_OF_MEMORY); - - nsAutoTestThread otherTestThread; - NS_ENSURE_TRUE(otherTestThread, NS_ERROR_FAILURE); - - rv = otherTestThread->Dispatch(proxyGetter, NS_DISPATCH_SYNC); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(proxy, NS_ERROR_FAILURE); - - for (PRUint32 otherCounter = 0; otherCounter < 5;) { - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE); - } - - return NS_OK; -} - -nsresult -TestChainedProxy() -{ - LOG(("--- Running TestChainedProxy ---")); - - nsRefPtr<ChainedProxyRunnable> runnable = - new ChainedProxyRunnable(gMainThread); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - nsCOMPtr<nsIRunnable> proxy; - nsresult rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), - runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - // This will do a test->main call - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - - runnable = new ChainedProxyRunnable(gTestThread); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable, - NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - // This will do a main->test call - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - - runnable = new ChainedProxyRunnable(gMainThread); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable, - NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - // This will do a main->main call - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - - runnable = new ChainedProxyRunnable(gTestThread); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable, - NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - // This will do a test->test call - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - - runnable = new ChainedProxyRunnable(gMainThread, gTestThread); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable, - NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - // This will do a test->main->test call - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -nsresult -TestReleaseOfRealObjects() -{ - LOG(("--- Running TestReleaseOfRealObjects ---")); - - PRUint32 counter = 0, otherCounter = 0; - - nsRefPtr<IncrementingRunnable> runnable(new IncrementingRunnable(&counter)); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - nsCOMPtr<nsIRunnable> proxy1; - nsresult rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), - runnable, NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy1)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr<nsIRunnable> proxy2; - rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable, - NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy2)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr<nsIRunnable> proxy3; - rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable, - NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy3)); - NS_ENSURE_SUCCESS(rv, rv); - - NS_ENSURE_FALSE(proxy1 == proxy2, NS_ERROR_FAILURE); - NS_ENSURE_TRUE(proxy2 == proxy3, NS_ERROR_FAILURE); - proxy3 = nsnull; - - rv = proxy1->Run(); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE); - - rv = proxy2->Run(); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE); - - runnable = nsnull; - - rv = proxy1->Run(); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE); - - rv = proxy2->Run(); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE); - - proxy1 = nsnull; - - rv = proxy2->Run(); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE); - - return NS_OK; -} - -nsresult -TestCurrentThreadProxy() -{ - LOG(("--- Running TestCurrentThreadProxy ---")); - - PRUint32 counter = 0, otherCounter = 0; - nsRefPtr<IncrementingRunnable> runnable(new IncrementingRunnable(&counter)); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - nsCOMPtr<nsIRunnable> proxy1; - nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), - runnable, NS_PROXY_SYNC, - getter_AddRefs(proxy1)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr<nsIRunnable> proxy2; - rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), runnable, - NS_PROXY_SYNC | NS_PROXY_ALWAYS, - getter_AddRefs(proxy2)); - NS_ENSURE_SUCCESS(rv, rv); - - NS_ENSURE_FALSE(proxy1 == proxy2, NS_ERROR_FAILURE); - - nsCOMPtr<nsIRunnable> realRunnable(do_QueryInterface(runnable)); - NS_ENSURE_TRUE(realRunnable, NS_ERROR_FAILURE); - - NS_ENSURE_TRUE(static_cast<void*>(realRunnable) == static_cast<void*>(runnable), - NS_ERROR_FAILURE); - - rv = proxy1->Run(); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE); - - rv = proxy2->Run(); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(counter == ++otherCounter, NS_ERROR_FAILURE); - - return NS_OK; -} - -nsresult -TestAsyncProxy() -{ - LOG(("--- Running TestAsyncProxy ---")); - - // Test async proxies to the current thread. - - PRUint32 counter = 0; - nsRefPtr<SimpleRunnable> runnable(new IncrementingRunnable(&counter)); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - nsCOMPtr<nsIRunnable> proxy; - nsresult rv = GetProxyForObject(gMainThread, NS_GET_IID(nsIRunnable), - runnable, NS_PROXY_ASYNC, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - runnable = nsnull; - - for (PRUint32 i = 0; i < 5; i++) { - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - } - - while (counter < 5) { - rv = NS_ProcessPendingEvents(gMainThread, PR_SecondsToInterval(1)); - NS_ENSURE_SUCCESS(rv, rv); - } - - // Now test async proxies to another thread. - - Mutex* counterLock = new Mutex("counterLock"); - NS_ENSURE_TRUE(counterLock, NS_ERROR_OUT_OF_MEMORY); - - counter = 0; - runnable = new IncrementingRunnable(&counter, counterLock); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), runnable, - NS_PROXY_ASYNC, getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - for (PRUint32 i = 0; i < 5; i++) { - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - } - - PRUint32 safeCounter = 0; - while (safeCounter < 5) { - rv = NS_ProcessPendingEvents(gMainThread, PR_SecondsToInterval(1)); - NS_ENSURE_SUCCESS(rv, rv); - - MutexAutoLock lock(*counterLock); - safeCounter = counter; - } - - delete counterLock; - - // Now test async proxies to another thread that create sync proxies to this - // thread. - - runnable = new ChainedProxyRunnable(gMainThread); - NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); - - rv = GetProxyForObject(gTestThread, NS_GET_IID(nsIRunnable), - runnable, NS_PROXY_ASYNC, - getter_AddRefs(proxy)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = proxy->Run(); - NS_ENSURE_SUCCESS(rv, rv); - - // That was async, so make sure to wait for all the events on the test thread - // to be processed before we return. This is easy to do with an empty sync - // event. - nsCOMPtr<nsIRunnable> flusher = new nsRunnable(); - NS_ENSURE_TRUE(flusher, NS_ERROR_OUT_OF_MEMORY); - - LOG(("Flushing events on test thread")); - - rv = gTestThread->Dispatch(flusher, NS_DISPATCH_SYNC); - NS_ENSURE_SUCCESS(rv, rv); - - LOG(("Flushing events completed")); - - return NS_OK; -} - -int main(int argc, char** argv) -{ - ScopedXPCOM xpcom(TEST_NAME); - NS_ENSURE_FALSE(xpcom.failed(), 1); - - nsCOMPtr<nsIThread> mainThread(do_GetMainThread()); - NS_ENSURE_TRUE(mainThread, 1); - - LOG(("Got main thread")); - gMainThread = mainThread; - - nsAutoTestThread testThread(&gTestThread); - NS_ENSURE_TRUE(testThread, 1); - - static TestFuncPtr testsToRun[] = { - TestTargetThread, - // TestNonThreadsafeProxy, /* Not currently supported! */ - TestChainedProxy, - TestReleaseOfRealObjects, - TestCurrentThreadProxy, - TestAsyncProxy - }; - static PRUint32 testCount = sizeof(testsToRun) / sizeof(testsToRun[0]); - - for (PRUint32 i = 0; i < testCount; i++) { - nsresult rv = testsToRun[i](); - NS_ENSURE_SUCCESS(rv, 1); - } - - LOG(("--- Finished all tests ---")); - return 0; -}
--- a/xpcom/tests/TestThreadPoolListener.cpp +++ b/xpcom/tests/TestThreadPoolListener.cpp @@ -32,17 +32,16 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "TestHarness.h" -#include "nsIProxyObjectManager.h" #include "nsIThread.h" #include "nsIThreadPool.h" #include "nsThreadUtils.h" #include "nsXPCOMCIDInternal.h" #include "pratom.h" #include "prinrval.h" #include "prmon.h" @@ -173,23 +172,16 @@ int main(int argc, char** argv) nsIThread* shutDownThreadList[NUMBER_OF_THREADS] = { nsnull }; gShutDownThreadList = shutDownThreadList; AutoCreateAndDestroyReentrantMonitor newMon(&gReentrantMonitor); NS_ENSURE_TRUE(gReentrantMonitor, 1); nsresult rv; - // Grab the proxy service before messing with the thread pool. This is a - // workaround for bug 449822 where the thread pool shutdown can create two - // instances of the proxy service and hang. - nsCOMPtr<nsIProxyObjectManager> proxyObjMgr = - do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr<nsIThreadPool> pool = do_CreateInstance(NS_THREADPOOL_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, 1); rv = pool->SetThreadLimit(NUMBER_OF_THREADS); NS_ENSURE_SUCCESS(rv, 1); rv = pool->SetIdleThreadLimit(NUMBER_OF_THREADS);
--- a/xpcom/threads/TimerThread.cpp +++ b/xpcom/threads/TimerThread.cpp @@ -41,17 +41,16 @@ #include "nsTimerImpl.h" #include "TimerThread.h" #include "nsThreadUtils.h" #include "pratom.h" #include "nsIObserverService.h" #include "nsIServiceManager.h" -#include "nsIProxyObjectManager.h" #include "mozilla/Services.h" #include <math.h> using namespace mozilla; NS_IMPL_THREADSAFE_ISUPPORTS2(TimerThread, nsIRunnable, nsIObserver) @@ -75,16 +74,45 @@ TimerThread::~TimerThread() } nsresult TimerThread::InitLocks() { return NS_OK; } +namespace { + +class TimerObserverRunnable : public nsRunnable +{ +public: + TimerObserverRunnable(nsIObserver* observer) + : mObserver(observer) + { } + + NS_DECL_NSIRUNNABLE + +private: + nsCOMPtr<nsIObserver> mObserver; +}; + +NS_IMETHODIMP +TimerObserverRunnable::Run() +{ + nsCOMPtr<nsIObserverService> observerService = + mozilla::services::GetObserverService(); + if (observerService) { + observerService->AddObserver(mObserver, "sleep_notification", PR_FALSE); + observerService->AddObserver(mObserver, "wake_notification", PR_FALSE); + } + return NS_OK; +} + +} // anonymous namespace + nsresult TimerThread::Init() { PR_LOG(gTimerLog, PR_LOG_DEBUG, ("TimerThread::Init [%d]\n", mInitialized)); if (mInitialized) { if (!mThread) return NS_ERROR_FAILURE; @@ -93,31 +121,22 @@ nsresult TimerThread::Init() if (PR_ATOMIC_SET(&mInitInProgress, 1) == 0) { // We hold on to mThread to keep the thread alive. nsresult rv = NS_NewThread(getter_AddRefs(mThread), this); if (NS_FAILED(rv)) { mThread = nsnull; } else { - nsCOMPtr<nsIObserverService> observerService = - mozilla::services::GetObserverService(); - // We must not use the observer service from a background thread! - if (observerService && !NS_IsMainThread()) { - nsCOMPtr<nsIObserverService> result = nsnull; - NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, - NS_GET_IID(nsIObserverService), - observerService, NS_PROXY_ASYNC, - getter_AddRefs(result)); - observerService.swap(result); + nsRefPtr<TimerObserverRunnable> r = new TimerObserverRunnable(this); + if (NS_IsMainThread()) { + r->Run(); } - // We'll be released at xpcom shutdown - if (observerService) { - observerService->AddObserver(this, "sleep_notification", false); - observerService->AddObserver(this, "wake_notification", false); + else { + NS_DispatchToMainThread(r); } } { MonitorAutoLock lock(mMonitor); mInitialized = true; mMonitor.NotifyAll(); }
--- a/xpcom/threads/nsThreadPool.cpp +++ b/xpcom/threads/nsThreadPool.cpp @@ -31,17 +31,16 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "nsIProxyObjectManager.h" #include "nsIClassInfoImpl.h" #include "nsThreadPool.h" #include "nsThreadManager.h" #include "nsThread.h" #include "nsMemory.h" #include "nsAutoPtr.h" #include "prinrval.h" #include "prlog.h" @@ -139,24 +138,18 @@ nsThreadPool::ShutdownThread(nsIThread * { LOG(("THRD-P(%p) shutdown async [%p]\n", this, thread)); // This method is responsible for calling Shutdown on |thread|. This must be // done from some other thread, so we use the main thread of the application. NS_ASSERTION(!NS_IsMainThread(), "wrong thread"); - nsCOMPtr<nsIThread> doomed; - NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIThread), thread, - NS_PROXY_ASYNC, getter_AddRefs(doomed)); - if (doomed) { - doomed->Shutdown(); - } else { - NS_WARNING("failed to construct proxy to main thread"); - } + nsRefPtr<nsIRunnable> r = NS_NewRunnableMethod(thread, &nsIThread::Shutdown); + NS_DispatchToMainThread(r); } NS_IMETHODIMP nsThreadPool::Run() { LOG(("THRD-P(%p) enter\n", this)); nsCOMPtr<nsIThread> current;