NS_IMETHODIMP_(nsrefcnt) nsTimerImpl::Release(void) { nsrefcnt count; NS_PRECONDITION(0 != mRefCnt, "dup release"); count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); NS_LOG_RELEASE(this, count, "nsTimerImpl"); if (count == 0) { mRefCnt = 1; /* stabilize */ /* enable this to find non-threadsafe destructors: */ /* NS_ASSERT_OWNINGTHREAD(nsTimerImpl); */ NS_DELETEXPCOM(this); return 0; } // If only one reference remains, and mArmed is set, then the ref must be // from the TimerThread::mTimers array, so we Cancel this timer to remove // the mTimers element, and return 0 if Cancel in fact disarmed the timer. // // We use an inlined version of nsTimerImpl::Cancel here to check for the // NS_ERROR_NOT_AVAILABLE code returned by gThread->RemoveTimer when this // timer is not found in the mTimers array -- i.e., when the timer was not // in fact armed once we acquired TimerThread::mLock, in spite of mArmed // being true here. That can happen if the armed timer is being fired by // TimerThread::Run as we race and test mArmed just before it is cleared by // the timer thread. If the RemoveTimer call below doesn't find this timer // in the mTimers array, then the last ref to this timer is held manually // and temporarily by the TimerThread, so we should fall through to the // final return and return 1, not 0. // // The original version of this thread-based timer code kept weak refs from // TimerThread::mTimers, removing this timer's weak ref in the destructor, // but that leads to double-destructions in the race described above, and // adding mArmed doesn't help, because destructors can't be deferred, once // begun. But by combining reference-counting and a specialized Release // method with "is this timer still in the mTimers array once we acquire // the TimerThread's lock" testing, we defer destruction until we're sure // that only one thread has its hot little hands on this timer. // // Note that both approaches preclude a timer creator, and everyone else // except the TimerThread who might have a strong ref, from dropping all // their strong refs without implicitly canceling the timer. Timers need // non-mTimers-element strong refs to stay alive. if (count == 1 && mArmed) { mCanceled = PR_TRUE; NS_ASSERTION(gThread, "An armed timer exists after the thread timer stopped."); if (NS_SUCCEEDED(gThread->RemoveTimer(this))) return 0; } return count; }
nsSystemPrincipal::Release() { NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release"); nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mJSPrincipals.refcount); NS_LOG_RELEASE(this, count, "nsSystemPrincipal"); if (count == 0) { NS_DELETEXPCOM(this); } return count; }
NS_IMETHODIMP_(nsrefcnt) xpctestNoisy::Release(void) { NS_PRECONDITION(0 != mRefCnt, "dup release"); --mRefCnt; printf("Noisy %d - decremented refcount to %d\n", mID, mRefCnt.get()); NS_LOG_RELEASE(this, mRefCnt, "xpctestNoisy"); if (mRefCnt == 0) { NS_DELETEXPCOM(this); return 0; } return mRefCnt; }
NS_IMETHODIMP_(nsrefcnt) npAPInsIInputStreamShim::Release(void) { NS_PRECONDITION(0 != mRefCnt, "dup release"); // Note that we intentionally don't check for owning thread safety. --mRefCnt; NS_LOG_RELEASE(this, mRefCnt, "npAPInsIInputStreamShim"); if (mRefCnt == 0) { mRefCnt = 1; /* stabilize */ NS_DELETEXPCOM(this); return 0; } return mRefCnt; }
nsrefcnt nsLDAPConnection::Release(void) { nsrefcnt count; NS_PRECONDITION(0 != mRefCnt, "dup release"); count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); NS_LOG_RELEASE(this, count, "nsLDAPConnection"); if (0 == count) { // As commented by danm: In the object's destructor, if by some // convoluted, indirect means it happens to run into some code // that temporarily references it (addref/release), then if the // refcount had been left at 0 the unexpected release would // attempt to reenter the object's destructor. // mRefCnt = 1; /* stabilize */ // If we have a mRunnable object, we need to make sure to lock it's // mLock before we try to DELETE. This is to avoid a race condition. // We also make sure to keep a strong reference to the runnable // object, to make sure it doesn't get GCed from underneath us, // while we are still holding a lock for instance. // if (mRunnable && mRunnable->mLock) { nsLDAPConnectionLoop *runnable = mRunnable; NS_ADDREF(runnable); PR_Lock(runnable->mLock); NS_DELETEXPCOM(this); PR_Unlock(runnable->mLock); NS_RELEASE(runnable); } else { NS_DELETEXPCOM(this); } return 0; } return count; }
NS_IMETHODIMP_(nsrefcnt) nsPrintProgress::Release(void) { nsrefcnt count; NS_PRECONDITION(0 != mRefCnt, "dup release"); count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); //NS_LOG_RELEASE(this, count, "nsPrintProgress"); if (0 == count) { mRefCnt = 1; /* stabilize */ /* enable this to find non-threadsafe destructors: */ /* NS_ASSERT_OWNINGTHREAD(nsPrintProgress); */ NS_DELETEXPCOM(this); return 0; } return count; }
// // callback for deleting the encodings from the nsObjectHashtable, mEncodings, // in the nsSOAPEncodingRegistry // static PRBool PR_CALLBACK DeleteEncodingEntry(nsHashKey *aKey, void *aData, void *aClosure) { NS_DELETEXPCOM((nsSOAPEncoding*)aData); return PR_TRUE; }
/** * See sbIMediaList */ NS_IMETHODIMP sbLocalDatabaseMediaListBase::EnumerateItemsByProperties(sbIPropertyArray* aProperties, sbIMediaListEnumerationListener* aEnumerationListener, PRUint16 aEnumerationType) { NS_ENSURE_ARG_POINTER(aProperties); NS_ENSURE_ARG_POINTER(aEnumerationListener); PRUint32 propertyCount; nsresult rv = aProperties->GetLength(&propertyCount); NS_ENSURE_SUCCESS(rv, rv); // It doesn't make sense to call this method without specifying any properties // so it is probably a caller error if we have none. NS_ENSURE_STATE(propertyCount); // The guidArray needs AddFilter called only once per property with an // enumerator that contains all the values. We were given an array of // id/value pairs, so this is a little tricky. We make a hash table that // uses the property id for a key and an array of values as its data. Then // we load the arrays in a loop and finally call AddFilter as an enumeration // function. sbStringArrayHash propertyHash; // Init with the propertyCount as the number of buckets to create. This will // probably be too many, but it's likely less than the default of 16. propertyHash.Init(propertyCount); nsCOMPtr<sbIPropertyManager> propMan = do_GetService(SB_PROPERTYMANAGER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); // Load the hash table with properties from the array. for (PRUint32 index = 0; index < propertyCount; index++) { // Get the property. nsCOMPtr<sbIProperty> property; rv = aProperties->GetPropertyAt(index, getter_AddRefs(property)); SB_CONTINUE_IF_FAILED(rv); // Get the id of the property. This will be the key for the hash table. nsString propertyID; rv = property->GetId(propertyID); SB_CONTINUE_IF_FAILED(rv); // Get the string array associated with the key. If it doesn't yet exist // then we need to create it. sbStringArray* stringArray; bool arrayExists = propertyHash.Get(propertyID, &stringArray); if (!arrayExists) { NS_NEWXPCOM(stringArray, sbStringArray); SB_CONTINUE_IF_FALSE(stringArray); // Try to add the array to the hash table. bool success = propertyHash.Put(propertyID, stringArray); if (!success) { NS_WARNING("Failed to add string array to property hash!"); // Make sure to delete the new array, otherwise it will leak. NS_DELETEXPCOM(stringArray); continue; } } NS_ASSERTION(stringArray, "Must have a valid pointer here!"); // Now we need a slot for the property value. nsString* valueString = stringArray->AppendElement(); SB_CONTINUE_IF_FALSE(valueString); // Make the value sortable and assign it nsCOMPtr<sbIPropertyInfo> info; rv = propMan->GetPropertyInfo(propertyID, getter_AddRefs(info)); SB_CONTINUE_IF_FAILED(rv); nsAutoString value; rv = property->GetValue(value); SB_CONTINUE_IF_FAILED(rv); nsAutoString sortableValue; rv = info->MakeSortable(value, *valueString); SB_CONTINUE_IF_FAILED(rv); } switch (aEnumerationType) { case sbIMediaList::ENUMERATIONTYPE_LOCKING: { NS_ENSURE_TRUE(mFullArrayMonitor, NS_ERROR_FAILURE); nsAutoMonitor mon(mFullArrayMonitor); // Don't reenter! NS_ENSURE_FALSE(mLockedEnumerationActive, NS_ERROR_FAILURE); mLockedEnumerationActive = PR_TRUE; PRUint16 stepResult; rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult); if (NS_SUCCEEDED(rv)) { if (stepResult == sbIMediaListEnumerationListener::CONTINUE) { rv = EnumerateItemsByPropertiesInternal(&propertyHash, aEnumerationListener); } else { // The user cancelled the enumeration. rv = NS_ERROR_ABORT; } } mLockedEnumerationActive = PR_FALSE; } break; // ENUMERATIONTYPE_LOCKING case sbIMediaList::ENUMERATIONTYPE_SNAPSHOT: { PRUint16 stepResult; rv = aEnumerationListener->OnEnumerationBegin(this, &stepResult); if (NS_SUCCEEDED(rv)) { if (stepResult == sbIMediaListEnumerationListener::CONTINUE) { rv = EnumerateItemsByPropertiesInternal(&propertyHash, aEnumerationListener); } else { // The user cancelled the enumeration. rv = NS_ERROR_ABORT; } } } break; // ENUMERATIONTYPE_SNAPSHOT default: { NS_NOTREACHED("Invalid enumeration type"); rv = NS_ERROR_INVALID_ARG; } break; } aEnumerationListener->OnEnumerationEnd(this, rv); return NS_OK; }