зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
6387ba06a1
Коммит
2d9e9c826b
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче