Fix for bug #2164. Balanced the NS_ADDREF and NS_RELEASE, which takes some doing, because it gets released in a module that did not add the reference (during Stop(), when all timers are released). This is bad design, methinks.

This commit is contained in:
mcmullen%netscape.com 1999-01-09 02:47:34 +00:00
Родитель 6387ba06a1
Коммит 2d9e9c826b
1 изменённых файлов: 68 добавлений и 25 удалений

Просмотреть файл

@ -32,10 +32,11 @@
#include <LComparator.h> #include <LComparator.h>
#pragma mark class TimerImpl #pragma mark class TimerImpl
//
// TimerImpl implements nsITimer API //========================================================================================
//
class TimerImpl : public nsITimer class TimerImpl : public nsITimer
// TimerImpl implements nsITimer API
//========================================================================================
{ {
private: private:
nsTimerCallbackFunc mCallbackFunc; nsTimerCallbackFunc mCallbackFunc;
@ -50,7 +51,7 @@ class TimerImpl : public nsITimer
TimerImpl(); TimerImpl();
virtual ~TimerImpl(){}; virtual ~TimerImpl();
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -81,11 +82,12 @@ class TimerImpl : public nsITimer
}; };
#pragma mark class TimerPeriodical #pragma mark class TimerPeriodical
//
//========================================================================================
class TimerPeriodical : public LPeriodical
// TimerPeriodical is a singleton LPeriodical subclass that fires // TimerPeriodical is a singleton LPeriodical subclass that fires
// off TimerImpl. The firing is done on idle // off TimerImpl. The firing is done on idle
// //========================================================================================
class TimerPeriodical : public LPeriodical
{ {
static TimerPeriodical * gPeriodical; static TimerPeriodical * gPeriodical;
@ -107,10 +109,11 @@ class TimerPeriodical : public LPeriodical
}; };
#pragma mark class TimerImplComparator #pragma mark class TimerImplComparator
//
// TimerImplComparator compares two TimerImpl //========================================================================================
//
class TimerImplComparator : public LComparator class TimerImplComparator : public LComparator
// TimerImplComparator compares two TimerImpl
//========================================================================================
{ {
virtual Int32 Compare( virtual Int32 Compare(
const void* inItemOne, const void* inItemOne,
@ -120,26 +123,37 @@ class TimerImplComparator : public LComparator
}; };
// //========================================================================================
// TimerImpl implementation // TimerImpl implementation
// //========================================================================================
static NS_DEFINE_IID(kITimerIID, NS_ITIMER_IID); static NS_DEFINE_IID(kITimerIID, NS_ITIMER_IID);
NS_IMPL_ISUPPORTS(TimerImpl, kITimerIID) NS_IMPL_ISUPPORTS(TimerImpl, kITimerIID)
//----------------------------------------------------------------------------------------
TimerImpl::TimerImpl() TimerImpl::TimerImpl()
//----------------------------------------------------------------------------------------
: mCallbackFunc(nsnull)
, mCallbackObject(nsnull)
, mClosure(nsnull)
, mDelay(0)
, mFireTime(0)
{ {
NS_INIT_REFCNT(); NS_INIT_REFCNT();
mCallbackFunc = NULL;
mCallbackObject = NULL;
mClosure = NULL;
mDelay = 0;
mFireTime = 0;
} }
//----------------------------------------------------------------------------------------
TimerImpl::~TimerImpl()
//----------------------------------------------------------------------------------------
{
NS_IF_RELEASE(mCallbackObject);
}
//----------------------------------------------------------------------------------------
nsresult TimerImpl::Init(nsTimerCallbackFunc aFunc, nsresult TimerImpl::Init(nsTimerCallbackFunc aFunc,
void *aClosure, void *aClosure,
PRUint32 aDelay) PRUint32 aDelay)
//----------------------------------------------------------------------------------------
{ {
mCallbackFunc = aFunc; mCallbackFunc = aFunc;
mClosure = aClosure; mClosure = aClosure;
@ -147,25 +161,35 @@ nsresult TimerImpl::Init(nsTimerCallbackFunc aFunc,
return TimerPeriodical::GetPeriodical()->AddTimer(this); return TimerPeriodical::GetPeriodical()->AddTimer(this);
} }
//----------------------------------------------------------------------------------------
nsresult TimerImpl::Init(nsITimerCallback *aCallback, nsresult TimerImpl::Init(nsITimerCallback *aCallback,
PRUint32 aDelay) PRUint32 aDelay)
//----------------------------------------------------------------------------------------
{ {
NS_ADDREF(aCallback);
mCallbackObject = aCallback; mCallbackObject = aCallback;
SetDelaySelf(aDelay); SetDelaySelf(aDelay);
return TimerPeriodical::GetPeriodical()->AddTimer(this); return TimerPeriodical::GetPeriodical()->AddTimer(this);
} }
//----------------------------------------------------------------------------------------
void TimerImpl::Cancel() void TimerImpl::Cancel()
//----------------------------------------------------------------------------------------
{ {
TimerPeriodical::GetPeriodical()->RemoveTimer(this); TimerPeriodical::GetPeriodical()->RemoveTimer(this);
} }
//----------------------------------------------------------------------------------------
PRUint32 TimerImpl::GetDelay() PRUint32 TimerImpl::GetDelay()
//----------------------------------------------------------------------------------------
{ {
return mDelay; return mDelay;
} }
//----------------------------------------------------------------------------------------
void TimerImpl::SetDelay(PRUint32 aDelay) void TimerImpl::SetDelay(PRUint32 aDelay)
//----------------------------------------------------------------------------------------
{ {
SetDelaySelf(aDelay); SetDelaySelf(aDelay);
// Make sure that timer was sorted // Make sure that timer was sorted
@ -175,29 +199,45 @@ void TimerImpl::SetDelay(PRUint32 aDelay)
NS_RELEASE(this); NS_RELEASE(this);
} }
//----------------------------------------------------------------------------------------
void* TimerImpl::GetClosure() void* TimerImpl::GetClosure()
//----------------------------------------------------------------------------------------
{ {
return mClosure; return mClosure;
} }
//----------------------------------------------------------------------------------------
void TimerImpl::Fire() void TimerImpl::Fire()
//----------------------------------------------------------------------------------------
{ {
if (mCallbackFunc != NULL) { if (mCallbackFunc != NULL)
{
(*mCallbackFunc)(this, mClosure); (*mCallbackFunc)(this, mClosure);
} }
else if (mCallbackObject != NULL) { else if (mCallbackObject != NULL)
mCallbackObject->Notify(this); // Fire the timer {
nsITimerCallback* object = mCallbackObject;
mCallbackObject = nsnull;
// because the Notify call will release it.
// We will release again it in the destructor if
// it is not null when we go away!
object->Notify(this); // Fire the timer
} }
} }
//----------------------------------------------------------------------------------------
void TimerImpl::SetDelaySelf( PRUint32 aDelay ) void TimerImpl::SetDelaySelf( PRUint32 aDelay )
//----------------------------------------------------------------------------------------
{ {
mDelay = aDelay; mDelay = aDelay;
mFireTime = TickCount() + (mDelay * 3) / 50; // We need mFireTime in ticks (1/60th) mFireTime = TickCount() + (mDelay * 3) / 50; // We need mFireTime in ticks (1/60th)
// but aDelay is in 1000th (60/1000 = 3/50) // but aDelay is in 1000th (60/1000 = 3/50)
NS_ADDREF(this); // Needed because the Stop() function will call NS_RELEASE on us when we fire.
} }
TimerPeriodical * TimerPeriodical::gPeriodical = NULL; TimerPeriodical * TimerPeriodical::gPeriodical = nsnull;
TimerPeriodical * TimerPeriodical::GetPeriodical() TimerPeriodical * TimerPeriodical::GetPeriodical()
{ {
@ -255,10 +295,13 @@ void TimerPeriodical::SpendTime( const EventRecord &inMacEvent)
{ {
if (timer->GetFireTime() <= inMacEvent.when) if (timer->GetFireTime() <= inMacEvent.when)
{ {
//NS_ADDREF(timer); // Another hairy fact:
// when firing the timer causes a URL to load, it calls Stop, which
// deletes all timers, including this one. Oi vey!
NS_ADDREF(timer);
RemoveTimer(timer); RemoveTimer(timer);
timer->Fire(); timer->Fire();
//NS_RELEASE(timer); NS_RELEASE(timer);
} }
else else
break; // Items are sorted, so we do not need to iterate until the end break; // Items are sorted, so we do not need to iterate until the end