fixes bug 210125 "need to be able to AsyncWait for closure only" r=dougt sr=bzbarsky

git-svn-id: svn://10.0.0.236/trunk@147597 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
darin%meer.net
2003-10-06 01:46:31 +00:00
parent fa7cb8115d
commit bc1bb52b19
73 changed files with 2530 additions and 2745 deletions

View File

@@ -42,60 +42,21 @@
#include "pratom.h"
#include "prmem.h"
// Ensures that the delete of a nsISupports object occurs on the main thread.
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static void* PR_CALLBACK
ReleaseDestructorEventHandler(PLEvent *self)
{
nsISupports* owner = (nsISupports*) PL_GetEventOwner(self);
NS_RELEASE(owner);
return nsnull;
}
static void PR_CALLBACK
ReleaseDestructorDestroyHandler(PLEvent *self)
{
delete self;
}
static void
NS_ProxyRelease(nsIEventQueue *eventQ, nsISupports *doomed, PRBool alwaysProxy=PR_FALSE)
{
if (!doomed)
return;
if (!eventQ) {
NS_RELEASE(doomed);
return;
}
if (!alwaysProxy) {
PRBool onCurrentThread = PR_FALSE;
eventQ->IsQueueOnCurrentThread(&onCurrentThread);
if (onCurrentThread) {
NS_RELEASE(doomed);
return;
}
}
PLEvent *ev = new PLEvent;
if (!ev) {
NS_ERROR("failed to allocate PLEvent");
// we do not release doomed here since it may cause a delete on the the
// wrong thread. better to leak than crash.
return;
}
PL_InitEvent(ev,
(void *) doomed,
ReleaseDestructorEventHandler,
ReleaseDestructorDestroyHandler);
PRStatus rv = eventQ->PostEvent(ev);
NS_ASSERTION(rv == PR_SUCCESS, "PostEvent failed");
}
/**
* Ensures that the delete of a nsISupports object occurs on the target thread.
*
* @param target
* the target thread where the doomed object should be released.
* @param doomed
* the doomed object; the object to be released on the target thread.
* @param alwaysProxy
* normally, if NS_ProxyRelease is called on the target thread, then the
* doomed object will released directly. however, if this parameter is
* true, then a PLEvent will always be posted to the target thread and
* the release will happen when that PLEvent is handled.
*/
NS_COM nsresult NS_ProxyRelease
(nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy=PR_FALSE);
#define NS_IMPL_PROXY_RELEASE(_class) \
@@ -109,6 +70,7 @@ NS_IMETHODIMP_(nsrefcnt) _class::Release(void)
{ \
mRefCnt = 1; /* stabilize */ \
PRBool callDirectly = PR_TRUE; \
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); \
nsCOMPtr<nsIEventQueueService> eventQService \
= do_GetService(kEventQueueServiceCID); \
NS_ASSERTION(eventQService, "event queue service is unavailable"); \
@@ -117,7 +79,7 @@ NS_IMETHODIMP_(nsrefcnt) _class::Release(void)
if (eventQService) { \
eventQService->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eventQ)); \
if (eventQ) \
eventQ->IsQueueOnCurrentThread(&callDirectly); \
eventQ->IsOnCurrentThread(&callDirectly); \
} \
\
if (callDirectly) \

View File

@@ -37,6 +37,7 @@ CPPSRCS = \
nsProxyEventClass.cpp \
nsProxyEventObject.cpp \
nsProxyObjectManager.cpp \
nsProxyRelease.cpp \
$(NULL)
DEFINES += -D_IMPL_NS_COM -DEXPORT_XPTC_API -DEXPORT_XPTI_API

View File

@@ -309,7 +309,7 @@ nsProxyObject::Release(void)
mRefCnt = 1; /* stabilize */
PRBool callDirectly;
mDestQueue->IsQueueOnCurrentThread(&callDirectly);
mDestQueue->IsOnCurrentThread(&callDirectly);
if (callDirectly)
{
@@ -466,7 +466,7 @@ nsProxyObject::Post( PRUint32 methodIndex,
// as the destination event queue.
if ( (methodIndex == 0) ||
(mProxyType & PROXY_SYNC &&
NS_SUCCEEDED(mDestQueue->IsQueueOnCurrentThread(&callDirectly)) &&
NS_SUCCEEDED(mDestQueue->IsOnCurrentThread(&callDirectly)) &&
callDirectly))
{

View File

@@ -209,7 +209,7 @@ nsProxyObjectManager::GetProxyForObject(nsIEventQueue *destQueue,
if (postQ && !(proxyType & PROXY_ASYNC) && !(proxyType & PROXY_ALWAYS))
{
PRBool aResult;
postQ->IsQueueOnCurrentThread(&aResult);
postQ->IsOnCurrentThread(&aResult);
if (aResult)
{

View File

@@ -0,0 +1,55 @@
#include "nsProxyRelease.h"
PR_STATIC_CALLBACK(void*)
HandleProxyReleaseEvent(PLEvent *self)
{
nsISupports* owner = (nsISupports*) self->owner;
NS_RELEASE(owner);
return nsnull;
}
PR_STATIC_CALLBACK(void)
DestroyProxyReleaseEvent(PLEvent *self)
{
delete self;
}
NS_COM nsresult
NS_ProxyRelease(nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy)
{
nsresult rv;
if (!target) {
NS_RELEASE(doomed);
return NS_OK;
}
if (!alwaysProxy) {
PRBool onCurrentThread = PR_FALSE;
rv = target->IsOnCurrentThread(&onCurrentThread);
if (NS_SUCCEEDED(rv) && onCurrentThread) {
NS_RELEASE(doomed);
return NS_OK;
}
}
PLEvent *ev = new PLEvent;
if (!ev) {
// we do not release doomed here since it may cause a delete on the
// wrong thread. better to leak than crash.
return NS_ERROR_OUT_OF_MEMORY;
}
PL_InitEvent(ev, doomed,
HandleProxyReleaseEvent,
DestroyProxyReleaseEvent);
rv = target->PostEvent(ev);
if (NS_FAILED(rv)) {
NS_WARNING("failed to post proxy release event");
PL_DestroyEvent(ev);
// again, it is better to leak the doomed object than risk crashing as
// a result of deleting it on the wrong thread.
}
return rv;
}