LazyIdleThread::Release() { nsrefcnt count = NS_AtomicDecrementRefcnt(mRefCnt); NS_LOG_RELEASE(this, count, "LazyIdleThread"); if (!count) { // Stabilize refcount. mRefCnt = 1; nsCOMPtr<nsIRunnable> runnable = NS_NewNonOwningRunnableMethod(this, &LazyIdleThread::SelfDestruct); NS_WARN_IF_FALSE(runnable, "Couldn't make runnable!"); if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) { MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); // The only way this could fail is if we're in shutdown, and in that case // threads should have been joined already. Deleting here isn't dangerous // anymore because we won't spin the event loop waiting to join the // thread. SelfDestruct(); } } return count; }
nsHttpTransaction::Release() { nsrefcnt count; NS_PRECONDITION(0 != mRefCnt, "dup release"); count = NS_AtomicDecrementRefcnt(mRefCnt); NS_LOG_RELEASE(this, count, "nsHttpTransaction"); if (0 == count) { mRefCnt = 1; /* stablize */ // it is essential that the transaction be destroyed on the consumer // thread (we could be holding the last reference to our consumer). DeleteSelfOnConsumerThread(); return 0; } return count; }
NS_IMETHODIMP_(nsrefcnt) nsPrintProgress::Release(void) { nsrefcnt count; NS_PRECONDITION(0 != mRefCnt, "dup release"); count = NS_AtomicDecrementRefcnt(mRefCnt); //NS_LOG_RELEASE(this, count, "nsPrintProgress"); if (0 == count) { mRefCnt = 1; /* stabilize */ /* enable this to find non-threadsafe destructors: */ /* NS_ASSERT_OWNINGTHREAD(nsPrintProgress); */ delete this; return 0; } return count; }
nsrefcnt nsXPCWrappedJS::Release(void) { NS_PRECONDITION(0 != mRefCnt, "dup release"); if (mMainThreadOnly && !NS_IsMainThread()) { // We'd like to abort here, but this can happen if someone uses a proxy // for the nsXPCWrappedJS. nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); // If we can't get the main thread anymore we just leak, but this really // shouldn't happen. NS_ASSERTION(mainThread, "Can't get main thread, leaking nsXPCWrappedJS!"); if (mainThread) { NS_ProxyRelease(mainThread, static_cast<nsIXPConnectWrappedJS*>(this)); } return mRefCnt; } // need to take the map lock here to prevent GetNewOrUsed from trying // to reuse a wrapper on one thread while it's being destroyed on another XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); XPCAutoLock lock(rt->GetMapLock()); do_decrement: nsrefcnt cnt = NS_AtomicDecrementRefcnt(mRefCnt); NS_LOG_RELEASE(this, cnt, "nsXPCWrappedJS"); if (0 == cnt) { delete this; // also unlinks us from chain return 0; } if (1 == cnt) { if (IsValid()) RemoveFromRootSet(rt->GetMapLock()); // If we are not the root wrapper or if we are not being used from a // weak reference, then this extra ref is not needed and we can let // ourself be deleted. // Note: HasWeakReferences() could only return true for the root. if (!HasWeakReferences()) goto do_decrement; } return cnt; }
nsrefcnt xptiInterfaceInfo::Release(void) { xptiInterfaceEntry* entry = mEntry; nsrefcnt cnt = NS_AtomicDecrementRefcnt(mRefCnt); NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo"); if(!cnt) { nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor()); LOG_INFO_MONITOR_ENTRY; // If GetInterfaceInfo added and *released* a reference before we // acquired the monitor then 'this' might already be dead. In that // case we would not want to try to access any instance data. We // would want to bail immediately. If 'this' is already dead then the // entry will no longer have a pointer to 'this'. So, we can protect // ourselves from danger without more aggressive locking. if(entry && !entry->InterfaceInfoEquals(this)) return 0; // If GetInterfaceInfo added a reference before we acquired the monitor // then we want to bail out of here without destorying the object. if(mRefCnt) return 1; if(mEntry) { mEntry->LockedInterfaceInfoDeathNotification(); mEntry = nsnull; } delete this; return 0; } return cnt; }