зеркало из https://github.com/mozilla/pjs.git
Landing timer move on windows.
This commit is contained in:
Родитель
342b5083f1
Коммит
fecd737d22
|
@ -71,6 +71,7 @@ LLIBS= \
|
|||
$(DIST)\lib\plc3.lib \
|
||||
$(DIST)\lib\caps.lib \
|
||||
$(DIST)\lib\oji.lib \
|
||||
$(DIST)\lib\timer_s.lib \
|
||||
$(LIBNSPR)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
|
|
@ -45,8 +45,6 @@ EXPORTS = \
|
|||
nsIDeviceContextSpecFactory.h \
|
||||
nsIDrawingSurface.h \
|
||||
nsColorNameIDs.h \
|
||||
nsITimer.h \
|
||||
nsITimerCallback.h \
|
||||
$(NULL)
|
||||
|
||||
MODULE=raptor
|
||||
|
|
|
@ -23,9 +23,9 @@ DIRS = windows
|
|||
LIBRARY_NAME=raptorgfx_s
|
||||
MODULE=raptor
|
||||
!ifdef NECKO
|
||||
REQUIRES=util img xpcom raptor necko
|
||||
REQUIRES=util img xpcom raptor necko timer
|
||||
!else
|
||||
REQUIRES=util img xpcom raptor netlib
|
||||
REQUIRES=util img xpcom raptor netlib timer
|
||||
!endif
|
||||
|
||||
DEFINES=-D_IMPL_NS_GFX -DWIN32_LEAN_AND_MEAN
|
||||
|
@ -72,7 +72,7 @@ libs:: $(LIBRARY)
|
|||
install::
|
||||
$(MAKE_INSTALL) icon_0.gif $(DIST)\bin\res\gfx
|
||||
$(MAKE_INSTALL) icon_1.gif $(DIST)\bin\res\gfx
|
||||
|
||||
|
||||
clobber::
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
rm -f $(PDBFILE).pdb
|
||||
|
|
|
@ -41,7 +41,6 @@ OBJS = \
|
|||
.\$(OBJDIR)\nsDeviceContextSpecWin.obj \
|
||||
.\$(OBJDIR)\nsDeviceContextSpecFactoryW.obj \
|
||||
.\$(OBJDIR)\nsGfxFactoryWin.obj \
|
||||
.\$(OBJDIR)\nsTimer.obj \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS= nsIRenderingContextWin.h \
|
||||
|
@ -78,6 +77,7 @@ LLIBS= \
|
|||
$(DIST)\lib\netlib.lib \
|
||||
!endif
|
||||
$(DIST)\lib\raptorgfx_s.lib \
|
||||
$(DIST)\lib\timer_s.lib \
|
||||
!if defined(NGLAYOUT_DDRAW)
|
||||
$(NGLAYOUT_DDRAW)\lib\ddraw.lib \
|
||||
!endif
|
||||
|
@ -107,4 +107,3 @@ install:: $(DLL)
|
|||
clobber::
|
||||
rm -f $(DIST)\bin\$(DLLNAME).dll
|
||||
rm -f $(DIST)\lib\$(DLLNAME).lib
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ LLIBS= \
|
|||
$(DIST)\lib\raptorevents_s.lib \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(DIST)\lib\raptorgfxwin.lib \
|
||||
$(DIST)\lib\timer_s.lib \
|
||||
$(DIST)\lib\raptorhtmlpars.lib \
|
||||
$(DIST)\lib\jsdom.lib \
|
||||
!ifdef NECKO
|
||||
|
|
|
@ -66,6 +66,7 @@ LLIBS= \
|
|||
!else
|
||||
$(DIST)\lib\netlib.lib \
|
||||
!endif
|
||||
$(DIST)\lib\timer_s.lib \
|
||||
$(LIBNSPR) \
|
||||
$(DIST)\lib\js32$(VERSION_NUMBER).lib
|
||||
|
||||
|
|
|
@ -33,14 +33,15 @@ CPP_OBJS= \
|
|||
.\$(OBJDIR)\nsMsgFactory.obj \
|
||||
$(NULL)
|
||||
|
||||
LLIBS= \
|
||||
LLIBS= \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(DIST)\lib\msgbaseutil.lib \
|
||||
$(DIST)\lib\msgbase_s.lib \
|
||||
$(DIST)\lib\msgsearch_s.lib \
|
||||
$(DIST)\lib\msgsearch_s.lib \
|
||||
$(DIST)\lib\netlib.lib \
|
||||
$(DIST)\lib\raptorgfxwin.lib \
|
||||
$(LIBNSPR) \
|
||||
$(DIST)\lib\raptorgfxwin.lib \
|
||||
$(DIST)\lib\timer_s.lib \
|
||||
$(LIBNSPR) \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
|
|
@ -49,6 +49,7 @@ DIRS = \
|
|||
modules\libjar \
|
||||
modules\libutil \
|
||||
sun-java \
|
||||
timer \
|
||||
js \
|
||||
modules\security\freenav \
|
||||
modules\libimg \
|
||||
|
|
|
@ -38,6 +38,7 @@ LLIBS=\
|
|||
$(DIST)\lib\rdfdatasource_s.lib \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(DIST)\lib\raptorgfxwin.lib \
|
||||
$(DIST)\lib\timer_s.lib \
|
||||
!ifdef NECKO
|
||||
$(DIST)\lib\neckoutil_s.lib \
|
||||
!else
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#ifndef nsITimer_h___
|
||||
#define nsITimer_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsITimer;
|
||||
class nsITimerCallback;
|
||||
|
||||
// Implementations of nsITimer should be written such that there are no limitations
|
||||
// on what can be called by the TimerCallbackFunc. On platforms like the Macintosh this
|
||||
// means that callback functions must be called from the main event loop NOT from
|
||||
// an interrupt.
|
||||
|
||||
/// Signature of timer callback function
|
||||
typedef void
|
||||
(*nsTimerCallbackFunc) (nsITimer *aTimer, void *aClosure);
|
||||
|
||||
/// Interface IID for nsITimer
|
||||
#define NS_ITIMER_IID \
|
||||
{ 0x497eed20, 0xb740, 0x11d1, \
|
||||
{ 0x9b, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
|
||||
|
||||
/**
|
||||
* Timer class, used to invoke a function or method after a fixed
|
||||
* millisecond interval. <B>Note that this interface is subject to
|
||||
* change!</B>
|
||||
*/
|
||||
class nsITimer : public nsISupports {
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ITIMER_IID)
|
||||
|
||||
/**
|
||||
* Initialize a timer to fire after the given millisecond interval.
|
||||
* This version takes a function to call and a closure to pass to
|
||||
* that function.
|
||||
*
|
||||
* @param aFunc - The function to invoke
|
||||
* @param aClosure - an opaque pointer to pass to that function
|
||||
* @param aRepeat - (Not yet implemented) One-shot or repeating
|
||||
* @param aDelay - The millisecond interval
|
||||
* @result - NS_OK if this operation was successful
|
||||
*/
|
||||
virtual nsresult Init(nsTimerCallbackFunc aFunc,
|
||||
void *aClosure,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay)=0;
|
||||
|
||||
/**
|
||||
* Initialize a timer to fire after the given millisecond interval.
|
||||
* This version takes an interface of type <code>nsITimerCallback</code>.
|
||||
* The <code>Notify</code> method of this method is invoked.
|
||||
*
|
||||
* @param aCallback - The interface to notify
|
||||
* @param aRepeat - (Not yet implemented) One-shot or repeating
|
||||
* @param aDelay - The millisecond interval
|
||||
* @result - NS_OK if this operation was successful
|
||||
*/
|
||||
virtual nsresult Init(nsITimerCallback *aCallback,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay)=0;
|
||||
|
||||
/// Cancels the timeout
|
||||
virtual void Cancel()=0;
|
||||
|
||||
/// @return the millisecond delay of the timeout
|
||||
virtual PRUint32 GetDelay()=0;
|
||||
|
||||
/// Change the millisecond interval for the timeout
|
||||
virtual void SetDelay(PRUint32 aDelay)=0;
|
||||
|
||||
/// @return the opaque pointer
|
||||
virtual void* GetClosure()=0;
|
||||
};
|
||||
|
||||
/** Factory method for creating an nsITimer */
|
||||
extern
|
||||
#ifdef XP_MAC // On the macintosh, this is built into the network library.
|
||||
NS_NET
|
||||
#else
|
||||
NS_TIMER
|
||||
#endif
|
||||
nsresult NS_NewTimer(nsITimer** aInstancePtrResult);
|
||||
|
||||
#endif
|
|
@ -1,362 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsITimer.h"
|
||||
#include "nsITimerCallback.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prlog.h"
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <OS.h>
|
||||
#include <Application.h>
|
||||
#include <Autolock.h>
|
||||
#include <Message.h>
|
||||
#include <signal.h>
|
||||
#include <List.h>
|
||||
#include <prthread.h>
|
||||
|
||||
static NS_DEFINE_IID(kITimerIID, NS_ITIMER_IID);
|
||||
|
||||
struct ThreadInterfaceData
|
||||
{
|
||||
void *data;
|
||||
int32 sync;
|
||||
};
|
||||
|
||||
static sem_id my_find_sem(const char *name)
|
||||
{
|
||||
sem_id ret = B_ERROR;
|
||||
|
||||
/* Get the sem_info for every sempahore in this team. */
|
||||
sem_info info;
|
||||
int32 cookie = 0;
|
||||
|
||||
while(get_next_sem_info(0, &cookie, &info) == B_OK)
|
||||
if(strcmp(name, info.name) == 0)
|
||||
{
|
||||
ret = info.sem;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
class TimerImpl;
|
||||
class TimerManager;
|
||||
|
||||
class TimerManager : public BList
|
||||
{
|
||||
public:
|
||||
TimerManager();
|
||||
~TimerManager();
|
||||
void AddRequest(TimerImpl *);
|
||||
bool RemoveRequest(TimerImpl *);
|
||||
|
||||
private:
|
||||
BLocker mLocker;
|
||||
sem_id mSyncSem;
|
||||
thread_id mTimerThreadID;
|
||||
bool mQuitRequested;
|
||||
|
||||
static int32 sTimerThreadFunc(void *);
|
||||
int32 TimerThreadFunc();
|
||||
TimerImpl *FirstRequest() { return (TimerImpl *)FirstItem(); }
|
||||
};
|
||||
|
||||
|
||||
class TimerImpl : public nsITimer
|
||||
{
|
||||
friend class TimerManager;
|
||||
public:
|
||||
TimerImpl();
|
||||
virtual ~TimerImpl();
|
||||
|
||||
virtual nsresult Init(nsTimerCallbackFunc aFunc,
|
||||
void *aClosure,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay);
|
||||
|
||||
virtual nsresult Init(nsITimerCallback *aCallback,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual void Cancel();
|
||||
virtual PRUint32 GetDelay() { return mDelay; }
|
||||
virtual void SetDelay(PRUint32);
|
||||
virtual void* GetClosure() { return mClosure; }
|
||||
|
||||
void FireTimeout();
|
||||
|
||||
private:
|
||||
nsresult Init(PRUint32 aDelay); // Initialize the timer.
|
||||
|
||||
bigtime_t mWhen; // Time when this request should be done
|
||||
PRUint32 mDelay; // The delay set in Init()
|
||||
nsTimerCallbackFunc mFunc; // The function to call back when expired
|
||||
void *mClosure; // The argumnet to pass it.
|
||||
nsITimerCallback *mCallback; // An interface to notify when expired.
|
||||
bool mCanceled;
|
||||
PRThread *mThread;
|
||||
// PRBool mRepeat; // A repeat, not implemented yet.
|
||||
|
||||
public:
|
||||
static TimerManager sTimerManager;
|
||||
};
|
||||
|
||||
TimerManager TimerImpl::sTimerManager;
|
||||
|
||||
TimerManager::TimerManager()
|
||||
: BList(40)
|
||||
{
|
||||
mQuitRequested = false;
|
||||
mSyncSem = create_sem(0, "timer sync");
|
||||
if(mSyncSem < 0)
|
||||
debugger("Failed to create sem...");
|
||||
|
||||
mTimerThreadID = spawn_thread(&sTimerThreadFunc, "timer roster", B_URGENT_DISPLAY_PRIORITY, (void *)this);
|
||||
if(mTimerThreadID < B_OK)
|
||||
// is it the right way ?
|
||||
debugger("Failed to spawn timer thread...");
|
||||
|
||||
resume_thread(mTimerThreadID);
|
||||
}
|
||||
|
||||
TimerManager::~TimerManager()
|
||||
{
|
||||
// should we empty the list here and NS_RELEASE ?
|
||||
mQuitRequested = true;
|
||||
delete_sem(mSyncSem);
|
||||
|
||||
int32 junk;
|
||||
wait_for_thread(mTimerThreadID, &junk);
|
||||
}
|
||||
|
||||
void TimerManager::AddRequest(TimerImpl *inRequest)
|
||||
{
|
||||
if(mLocker.Lock())
|
||||
{
|
||||
NS_ADDREF(inRequest); // this is for the timer list
|
||||
|
||||
// insert sorted into timer event list
|
||||
int32 count = CountItems();
|
||||
int32 pos;
|
||||
for(pos = 0; pos < count; pos++)
|
||||
{
|
||||
TimerImpl *entry = (TimerImpl *)ItemAtFast(pos);
|
||||
if(entry->mWhen > inRequest->mWhen)
|
||||
break;
|
||||
}
|
||||
AddItem(inRequest, pos);
|
||||
|
||||
if(pos == 0)
|
||||
// We need to wake the thread to wait on the newly added event
|
||||
release_sem(mSyncSem);
|
||||
|
||||
mLocker.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
bool TimerManager::RemoveRequest(TimerImpl *inRequest)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
if(mLocker.Lock())
|
||||
{
|
||||
if(RemoveItem(inRequest))
|
||||
{
|
||||
NS_RELEASE(inRequest);
|
||||
found = true;
|
||||
}
|
||||
|
||||
mLocker.Unlock();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
int32 TimerManager::sTimerThreadFunc(void *inData)
|
||||
{
|
||||
return ((TimerManager *)inData)->TimerThreadFunc();
|
||||
}
|
||||
|
||||
int32 TimerManager::TimerThreadFunc()
|
||||
{
|
||||
char portname[64];
|
||||
char semname[64];
|
||||
port_id eventport;
|
||||
sem_id syncsem;
|
||||
PRThread *cached = (PRThread *)-1;
|
||||
|
||||
while(! mQuitRequested)
|
||||
{
|
||||
TimerImpl *tobj = 0;
|
||||
|
||||
mLocker.Lock();
|
||||
|
||||
bigtime_t now = system_time();
|
||||
|
||||
// Fire expired pending requests
|
||||
while((tobj = FirstRequest()) != 0 && tobj->mWhen <= now)
|
||||
{
|
||||
RemoveItem((int32)0);
|
||||
mLocker.Unlock();
|
||||
|
||||
if(! tobj->mCanceled)
|
||||
{
|
||||
// fire it
|
||||
if(tobj->mThread != cached)
|
||||
{
|
||||
sprintf(portname, "event%lx", tobj->mThread);
|
||||
sprintf(semname, "sync%lx", tobj->mThread);
|
||||
|
||||
eventport = find_port(portname);
|
||||
syncsem = my_find_sem(semname);
|
||||
cached = tobj->mThread;
|
||||
}
|
||||
|
||||
// call timer synchronously so we're sure tobj is alive
|
||||
ThreadInterfaceData id;
|
||||
id.data = tobj;
|
||||
id.sync = true;
|
||||
if(write_port(eventport, 'WMti', &id, sizeof(id)) == B_OK)
|
||||
while(acquire_sem(syncsem) == B_INTERRUPTED)
|
||||
;
|
||||
}
|
||||
NS_RELEASE(tobj);
|
||||
|
||||
mLocker.Lock();
|
||||
}
|
||||
mLocker.Unlock();
|
||||
|
||||
if(acquire_sem_etc(mSyncSem, 1, B_ABSOLUTE_TIMEOUT,
|
||||
tobj ? tobj->mWhen : B_INFINITE_TIMEOUT) == B_BAD_SEM_ID)
|
||||
break;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// TimerImpl
|
||||
//
|
||||
void TimerImpl::FireTimeout()
|
||||
{
|
||||
if( ! mCanceled)
|
||||
{
|
||||
if(mFunc != NULL)
|
||||
(*mFunc)(this, mClosure); // If there's a function, call it.
|
||||
else if(mCallback != NULL)
|
||||
mCallback->Notify(this); // But if there's an interface, notify it.
|
||||
}
|
||||
}
|
||||
|
||||
TimerImpl::TimerImpl()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mFunc = 0;
|
||||
mCallback = 0;
|
||||
mDelay = 0;
|
||||
mClosure = 0;
|
||||
mWhen = 0;
|
||||
mCanceled = false;
|
||||
}
|
||||
|
||||
TimerImpl::~TimerImpl()
|
||||
{
|
||||
Cancel();
|
||||
NS_IF_RELEASE(mCallback);
|
||||
}
|
||||
|
||||
void TimerImpl::SetDelay(PRUint32 aDelay)
|
||||
{
|
||||
mDelay = aDelay;
|
||||
mWhen = system_time() + mDelay * 1000;
|
||||
|
||||
NS_ADDREF(this);
|
||||
if (TimerImpl::sTimerManager.RemoveRequest(this))
|
||||
TimerImpl::sTimerManager.AddRequest(this);
|
||||
// NS_RELEASE(this); // ?*?*?*?* doesn't work...
|
||||
Release(); // Is it the right way ?
|
||||
}
|
||||
|
||||
nsresult TimerImpl::Init(nsTimerCallbackFunc aFunc, void *aClosure,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay)
|
||||
{
|
||||
mFunc = aFunc;
|
||||
mClosure = aClosure;
|
||||
// mRepeat = aRepeat;
|
||||
|
||||
return Init(aDelay);
|
||||
}
|
||||
|
||||
nsresult TimerImpl::Init(nsITimerCallback *aCallback,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay)
|
||||
{
|
||||
mCallback = aCallback;
|
||||
NS_ADDREF(mCallback);
|
||||
// mRepeat = aRepeat;
|
||||
return Init(aDelay);
|
||||
}
|
||||
|
||||
|
||||
nsresult TimerImpl::Init(PRUint32 aDelay)
|
||||
{
|
||||
mDelay = aDelay;
|
||||
NS_ADDREF(this); // this is for clients of the timer
|
||||
mWhen = system_time() + aDelay * 1000;
|
||||
|
||||
mThread = PR_GetCurrentThread();
|
||||
|
||||
sTimerManager.AddRequest(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(TimerImpl, kITimerIID);
|
||||
|
||||
|
||||
void TimerImpl::Cancel()
|
||||
{
|
||||
mCanceled = true;
|
||||
TimerImpl::sTimerManager.RemoveRequest(this);
|
||||
}
|
||||
|
||||
NS_TIMER nsresult NS_NewTimer(nsITimer** aInstancePtrResult)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if(nsnull == aInstancePtrResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
TimerImpl *timer = new TimerImpl();
|
||||
if(nsnull == timer)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return timer->QueryInterface(kITimerIID, (void **) aInstancePtrResult);
|
||||
}
|
||||
|
||||
void nsTimerExpired(void *aCallData)
|
||||
{
|
||||
TimerImpl* timer = (TimerImpl *)aCallData;
|
||||
timer->FireTimeout();
|
||||
NS_RELEASE(timer);
|
||||
}
|
|
@ -1,357 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
//
|
||||
// Mac implementation of the nsITimer interface
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include "nsITimer.h"
|
||||
#include "nsITimerCallback.h"
|
||||
#include "prlog.h"
|
||||
#include "nsRepeater.h"
|
||||
|
||||
#include <list.h>
|
||||
#include <Events.h>
|
||||
|
||||
|
||||
|
||||
#pragma mark class TimerImpl
|
||||
|
||||
//========================================================================================
|
||||
class TimerImpl : public nsITimer
|
||||
// TimerImpl implements nsITimer API
|
||||
//========================================================================================
|
||||
{
|
||||
friend class TimerPeriodical;
|
||||
|
||||
private:
|
||||
nsTimerCallbackFunc mCallbackFunc;
|
||||
nsITimerCallback * mCallbackObject;
|
||||
void * mClosure;
|
||||
PRUint32 mDelay;
|
||||
PRUint32 mFireTime; // Timer should fire when TickCount >= this number
|
||||
TimerImpl * mPrev;
|
||||
TimerImpl * mNext;
|
||||
|
||||
public:
|
||||
|
||||
// constructors
|
||||
|
||||
TimerImpl();
|
||||
|
||||
virtual ~TimerImpl();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
PRUint32 GetFireTime() const { return mFireTime; }
|
||||
|
||||
void Fire();
|
||||
|
||||
// nsITimer overrides
|
||||
|
||||
virtual nsresult Init(nsTimerCallbackFunc aFunc,
|
||||
void *aClosure,
|
||||
PRUint32 aDelay);
|
||||
|
||||
virtual nsresult Init(nsITimerCallback *aCallback,
|
||||
PRUint32 aDelay);
|
||||
|
||||
virtual void Cancel();
|
||||
|
||||
virtual PRUint32 GetDelay();
|
||||
|
||||
virtual void SetDelay(PRUint32 aDelay);
|
||||
|
||||
virtual void* GetClosure();
|
||||
|
||||
#if DEBUG
|
||||
enum {
|
||||
eGoodTimerSignature = 'Barf',
|
||||
eDeletedTimerSignature = 'oops'
|
||||
};
|
||||
|
||||
Boolean IsGoodTimer() const { return (mSignature == eGoodTimerSignature); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Calculates mFireTime too
|
||||
void SetDelaySelf( PRUint32 aDelay );
|
||||
|
||||
#if DEBUG
|
||||
UInt32 mSignature;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#pragma mark class TimerPeriodical
|
||||
|
||||
//========================================================================================
|
||||
class TimerPeriodical : public Repeater
|
||||
// TimerPeriodical is a singleton Repeater subclass that fires
|
||||
// off TimerImpl. The firing is done on idle.
|
||||
//========================================================================================
|
||||
{
|
||||
static TimerPeriodical * gPeriodical;
|
||||
|
||||
TimerImpl* mTimers;
|
||||
|
||||
public:
|
||||
// Returns the singleton instance
|
||||
static TimerPeriodical * GetPeriodical();
|
||||
|
||||
TimerPeriodical();
|
||||
|
||||
virtual ~TimerPeriodical();
|
||||
|
||||
virtual void RepeatAction( const EventRecord &inMacEvent);
|
||||
|
||||
nsresult AddTimer( TimerImpl * aTimer);
|
||||
|
||||
nsresult RemoveTimer( TimerImpl * aTimer);
|
||||
|
||||
};
|
||||
|
||||
|
||||
//========================================================================================
|
||||
// TimerImpl implementation
|
||||
//========================================================================================
|
||||
|
||||
NS_IMPL_ISUPPORTS(TimerImpl, nsITimer::GetIID())
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
TimerImpl::TimerImpl()
|
||||
//----------------------------------------------------------------------------------------
|
||||
: mCallbackFunc(nsnull)
|
||||
, mCallbackObject(nsnull)
|
||||
, mClosure(nsnull)
|
||||
, mDelay(0)
|
||||
, mFireTime(0)
|
||||
, mPrev(nsnull)
|
||||
, mNext(nsnull)
|
||||
#if DEBUG
|
||||
, mSignature(eGoodTimerSignature)
|
||||
#endif
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
TimerImpl::~TimerImpl()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
Cancel();
|
||||
NS_IF_RELEASE(mCallbackObject);
|
||||
#if DEBUG
|
||||
mSignature = eDeletedTimerSignature;
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
nsresult TimerImpl::Init(nsTimerCallbackFunc aFunc,
|
||||
void *aClosure,
|
||||
PRUint32 aDelay)
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
mCallbackFunc = aFunc;
|
||||
mClosure = aClosure;
|
||||
SetDelaySelf(aDelay);
|
||||
return TimerPeriodical::GetPeriodical()->AddTimer(this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
nsresult TimerImpl::Init(nsITimerCallback *aCallback,
|
||||
PRUint32 aDelay)
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
NS_ADDREF(aCallback);
|
||||
mCallbackObject = aCallback;
|
||||
SetDelaySelf(aDelay);
|
||||
return TimerPeriodical::GetPeriodical()->AddTimer(this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void TimerImpl::Cancel()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
TimerPeriodical::GetPeriodical()->RemoveTimer(this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
PRUint32 TimerImpl::GetDelay()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
return mDelay;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void TimerImpl::SetDelay(PRUint32 aDelay)
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
SetDelaySelf(aDelay);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void* TimerImpl::GetClosure()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
return mClosure;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void TimerImpl::Fire()
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
NS_PRECONDITION(mRefCnt > 0, "Firing a disposed Timer!");
|
||||
if (mCallbackFunc != NULL) {
|
||||
(*mCallbackFunc)(this, mClosure);
|
||||
}
|
||||
else if (mCallbackObject != NULL) {
|
||||
mCallbackObject->Notify(this); // Fire the timer
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
void TimerImpl::SetDelaySelf( PRUint32 aDelay )
|
||||
//----------------------------------------------------------------------------------------
|
||||
{
|
||||
|
||||
mDelay = aDelay;
|
||||
mFireTime = TickCount() + (mDelay * 3) / 50; // We need mFireTime in ticks (1/60th)
|
||||
// but aDelay is in 1000th (60/1000 = 3/50)
|
||||
}
|
||||
|
||||
TimerPeriodical * TimerPeriodical::gPeriodical = nsnull;
|
||||
|
||||
TimerPeriodical * TimerPeriodical::GetPeriodical()
|
||||
{
|
||||
if (gPeriodical == NULL)
|
||||
gPeriodical = new TimerPeriodical();
|
||||
return gPeriodical;
|
||||
}
|
||||
|
||||
TimerPeriodical::TimerPeriodical()
|
||||
{
|
||||
mTimers = nsnull;
|
||||
}
|
||||
|
||||
TimerPeriodical::~TimerPeriodical()
|
||||
{
|
||||
PR_ASSERT(mTimers == 0);
|
||||
}
|
||||
|
||||
nsresult TimerPeriodical::AddTimer( TimerImpl * aTimer)
|
||||
{
|
||||
// make sure it's not already there
|
||||
RemoveTimer(aTimer);
|
||||
// keep list sorted by fire time
|
||||
if (mTimers)
|
||||
{
|
||||
if (aTimer->GetFireTime() < mTimers->GetFireTime())
|
||||
{
|
||||
mTimers->mPrev = aTimer;
|
||||
aTimer->mNext = mTimers;
|
||||
mTimers = aTimer;
|
||||
}
|
||||
else
|
||||
{
|
||||
TimerImpl *t = mTimers;
|
||||
TimerImpl *prevt;
|
||||
// we know we will enter the while loop at least the first
|
||||
// time, and thus prevt will be initialized
|
||||
while (t && (t->GetFireTime() <= aTimer->GetFireTime()))
|
||||
{
|
||||
prevt = t;
|
||||
t = t->mNext;
|
||||
}
|
||||
aTimer->mPrev = prevt;
|
||||
aTimer->mNext = prevt->mNext;
|
||||
prevt->mNext = aTimer;
|
||||
if (aTimer->mNext) aTimer->mNext->mPrev = aTimer;
|
||||
}
|
||||
}
|
||||
else mTimers = aTimer;
|
||||
|
||||
StartRepeating();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult TimerPeriodical::RemoveTimer( TimerImpl * aTimer)
|
||||
{
|
||||
TimerImpl* t = mTimers;
|
||||
TimerImpl* next_t = nsnull;
|
||||
if (t) next_t = t->mNext;
|
||||
while (t)
|
||||
{
|
||||
if (t == aTimer)
|
||||
{
|
||||
if (mTimers == t) mTimers = t->mNext;
|
||||
if (t->mPrev) t->mPrev->mNext = t->mNext;
|
||||
if (t->mNext) t->mNext->mPrev = t->mPrev;
|
||||
t->mNext = nsnull;
|
||||
t->mPrev = nsnull;
|
||||
}
|
||||
t = next_t;
|
||||
if (t) next_t = t->mNext;
|
||||
}
|
||||
|
||||
if ( mTimers == nsnull )
|
||||
StopRepeating();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Called through every event loop
|
||||
// Loops through the list of available timers, and
|
||||
// fires off the appropriate ones
|
||||
void TimerPeriodical::RepeatAction( const EventRecord &inMacEvent)
|
||||
{
|
||||
PRBool done = false;
|
||||
while (!done)
|
||||
{
|
||||
TimerImpl* t = mTimers;
|
||||
while (t)
|
||||
{
|
||||
NS_ASSERTION(t->IsGoodTimer(), "Bad timer!");
|
||||
|
||||
if (t->GetFireTime() <= inMacEvent.when)
|
||||
{
|
||||
RemoveTimer(t);
|
||||
t->Fire();
|
||||
break;
|
||||
}
|
||||
t = t->mNext;
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_TIMER nsresult NS_NewTimer(nsITimer** aInstancePtrResult)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
TimerImpl *timer = new TimerImpl();
|
||||
if (nsnull == timer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return timer->QueryInterface(nsITimer::GetIID(), (void **) aInstancePtrResult);
|
||||
}
|
|
@ -1,601 +0,0 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is the Mozilla OS/2 libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is John Fairhurst,
|
||||
* <john_fairhurst@iname.com>. Portions created by John Fairhurst are
|
||||
* Copyright (C) 1999 John Fairhurst. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
*/
|
||||
|
||||
#define INCL_DOS
|
||||
#define INCL_WIN
|
||||
#include <os2.h>
|
||||
|
||||
#include <limits.h> // UINT_MAX (don't ask...)
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nsHashtable.h"
|
||||
|
||||
//#define PROFILE_TIMERS // print stats on timer usage
|
||||
//#define VERIFY_THREADS // check timers are being used thread-correctly
|
||||
|
||||
#include "nsTimerOS2.h"
|
||||
|
||||
// Implementation of timers lifted from os2fe timer.cpp.
|
||||
// Which was itself lifted pretty much from the winfe.
|
||||
//
|
||||
// mjf 28-9-98
|
||||
//
|
||||
// Rewrite 16-3-1999 to work correctly in a multithreaded world:
|
||||
// Now, each thread has an nsTimerManager.
|
||||
// This has a Timer window owned by the thread, and
|
||||
// a queue (linked list) of timer objects.
|
||||
// There is a static hashtable of these TimerManager
|
||||
// object, keyed by TID. Thus things work. Ahem.
|
||||
//
|
||||
// Problem: nsTimerManagers are not cleaned up until
|
||||
// module unload time.
|
||||
//
|
||||
// Update 16-4-1999 to recycle timers and collect statistics on how effective
|
||||
// this is.
|
||||
|
||||
// Declarations, prototypes of useful functions
|
||||
MRESULT EXPENTRY fnwpTimer( HWND h, ULONG msg, MPARAM mp1, MPARAM mp2);
|
||||
#define NSTIMER_TIMER (TID_USERMAX - 2)
|
||||
#define TIMEOUT_NEVER ((ULONG)-1)
|
||||
#define TIMERCLASS ("WarpzillaTimerClass")
|
||||
#define TIMER_CACHESIZE 20
|
||||
|
||||
static TID QueryCurrentTID();
|
||||
|
||||
// Timer object (funky 'release' method for recycler)
|
||||
NS_IMPL_ADDREF(nsTimer)
|
||||
NS_IMPL_QUERY_INTERFACE(nsTimer, nsITimer::GetIID())
|
||||
|
||||
nsrefcnt nsTimer::Release()
|
||||
{
|
||||
if( --mRefCnt == 0)
|
||||
mManager->DisposeTimer( this);
|
||||
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
nsTimer::nsTimer( nsTimerManager *aManager)
|
||||
{
|
||||
Construct();
|
||||
mManager = aManager;
|
||||
}
|
||||
|
||||
void nsTimer::Construct()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mDelay = 0;
|
||||
mFunc = nsnull;
|
||||
mClosure = nsnull;
|
||||
mCallback = nsnull;
|
||||
mFireTime = 0;
|
||||
mNext = nsnull;
|
||||
}
|
||||
|
||||
void nsTimer::Destruct()
|
||||
{
|
||||
Cancel();
|
||||
}
|
||||
|
||||
nsTimer::~nsTimer()
|
||||
{
|
||||
Destruct();
|
||||
}
|
||||
|
||||
nsresult nsTimer::Init( nsTimerCallbackFunc aFunc,
|
||||
void *aClosure, PRUint32 aDelay)
|
||||
{
|
||||
mFunc = aFunc;
|
||||
mClosure = aClosure;
|
||||
|
||||
return mManager->InitTimer( this, aDelay);
|
||||
}
|
||||
|
||||
nsresult nsTimer::Init( nsITimerCallback *aCallback, PRUint32 aDelay)
|
||||
{
|
||||
mCallback = aCallback;
|
||||
NS_ADDREF(mCallback); // this is daft, but test14 traps without it
|
||||
|
||||
return mManager->InitTimer( this, aDelay);
|
||||
}
|
||||
|
||||
void nsTimer::Cancel()
|
||||
{
|
||||
if( mCallback || mFunc) // guard against double-cancel
|
||||
{
|
||||
mManager->CancelTimer( this);
|
||||
NS_IF_RELEASE(mCallback);
|
||||
mFunc = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
void nsTimer::Fire( ULONG aNow)
|
||||
{
|
||||
if( mFunc)
|
||||
(*mFunc)( this, mClosure);
|
||||
else if( mCallback)
|
||||
mCallback->Notify( this);
|
||||
}
|
||||
|
||||
// Timer manager
|
||||
|
||||
// First, GUI stuff.
|
||||
|
||||
nsTimerManager::nsTimerManager() : mTimerList(nsnull), mTimerSet(FALSE),
|
||||
mNextFire(TIMEOUT_NEVER), mHWNDTimer(0),
|
||||
mBusy(FALSE), mBase(nsnull), mSize(0)
|
||||
#ifdef PROFILE_TIMERS
|
||||
,mDeleted(0),mActive(0),mCount(0),mPeak(0)
|
||||
#endif
|
||||
{
|
||||
// As a part of the PM setup protocol (see somewhere under
|
||||
// http://www.mozilla.org/ports/os2/code_docs/), create a HMQ if
|
||||
// appropriate.
|
||||
if( FALSE == WinQueryQueueInfo( HMQ_CURRENT, 0, 0))
|
||||
{
|
||||
HAB hab = WinInitialize( 0);
|
||||
WinCreateMsgQueue( hab, 0);
|
||||
}
|
||||
// Register timer window class if we haven't done that yet.
|
||||
EnsureWndClass();
|
||||
|
||||
// Create timer window
|
||||
mHWNDTimer = WinCreateWindow( HWND_DESKTOP, TIMERCLASS, 0, 0, 0, 0, 0,
|
||||
0, HWND_DESKTOP, HWND_TOP, 0, 0, 0);
|
||||
NS_ASSERTION(mHWNDTimer, "Couldn't create Timer window");
|
||||
|
||||
// stick pointer to us in the window word
|
||||
WinSetWindowPtr( mHWNDTimer, QWL_USER, this);
|
||||
|
||||
#ifdef PROFILE_TIMERS
|
||||
mTID = QueryCurrentTID();
|
||||
#endif
|
||||
}
|
||||
|
||||
nsTimerManager::~nsTimerManager()
|
||||
{
|
||||
// I reckon PM has already gone down by this point.
|
||||
// There might be an API to do this (register listener for app shutdown)
|
||||
// at some point, or maybe when we get into the widget DLL.
|
||||
if( mHWNDTimer)
|
||||
WinDestroyWindow( mHWNDTimer);
|
||||
|
||||
#ifdef PROFILE_TIMERS
|
||||
printf( "\n----- Timer Statistics %d -----\n", (int)mTID);
|
||||
printf( " Calls to NS_NewTimer: %d\n", mCount);
|
||||
printf( " Actual timers created: %d\n", mPeak);
|
||||
double d = mCount ? (double)(mCount - mPeak) / (double)mCount : 0;
|
||||
printf( " Timers recycled: %d (%d%%)\n", mCount - mPeak, (int)(d*100.0));
|
||||
UINT i = mSize+mActive+mDeleted;
|
||||
printf( " Cache+Active+Deleted: %d\n", i);
|
||||
if( i != mPeak)
|
||||
printf( " WARNING: Timers leaked: %d\n", mPeak - i);
|
||||
printf( "------------------------------\n\n");
|
||||
#endif
|
||||
|
||||
// delete timers in the 'cache' list
|
||||
nsTimer *pTemp, *pNext = mBase;
|
||||
while( 0 != pNext)
|
||||
{
|
||||
pTemp = pNext->mNext;
|
||||
delete pNext;
|
||||
pNext = pTemp;
|
||||
// and then the 'active' list...
|
||||
if( 0 == pNext) { pNext = mTimerList; mTimerList = 0; }
|
||||
}
|
||||
}
|
||||
|
||||
void nsTimerManager::EnsureWndClass()
|
||||
{
|
||||
static BOOL bRegistered = FALSE;
|
||||
|
||||
if( !bRegistered)
|
||||
{
|
||||
BOOL rc = WinRegisterClass( 0, TIMERCLASS, fnwpTimer, 0, 4);
|
||||
NS_ASSERTION(rc,"Can't register class");
|
||||
bRegistered = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
MRESULT nsTimerManager::HandleMsg( ULONG msg, MPARAM mp1, MPARAM mp2)
|
||||
{
|
||||
MRESULT mRC = 0;
|
||||
|
||||
if( msg == WM_TIMER && SHORT1FROMMP(mp1) == NSTIMER_TIMER)
|
||||
{
|
||||
// Block only one entry into this function, or else.
|
||||
// (windows does this; don't completely understand or belive
|
||||
// it's necessary -- maybe if nested eventloops happen).
|
||||
if( !mBusy)
|
||||
{
|
||||
mBusy = TRUE;
|
||||
// see if we need to fork off any timeout functions
|
||||
if( mTimerList)
|
||||
ProcessTimeouts( 0);
|
||||
mBusy = FALSE;
|
||||
}
|
||||
else
|
||||
printf( "mBusy == TRUE but want to fire Timer!\n");
|
||||
}
|
||||
else
|
||||
mRC = WinDefWindowProc( mHWNDTimer, msg, mp1, mp2);
|
||||
|
||||
return mRC;
|
||||
}
|
||||
|
||||
void nsTimerManager::StopTimer()
|
||||
{
|
||||
WinStopTimer( 0/*hab*/, mHWNDTimer, NSTIMER_TIMER);
|
||||
}
|
||||
|
||||
void nsTimerManager::StartTimer( UINT aDelay)
|
||||
{
|
||||
WinStartTimer( 0/*hab*/, mHWNDTimer, NSTIMER_TIMER, aDelay);
|
||||
}
|
||||
|
||||
MRESULT EXPENTRY fnwpTimer( HWND h, ULONG msg, MPARAM mp1, MPARAM mp2)
|
||||
{
|
||||
nsTimerManager *pMgr = (nsTimerManager*) WinQueryWindowPtr( h, QWL_USER);
|
||||
MRESULT mRet = 0;
|
||||
if( pMgr)
|
||||
mRet = pMgr->HandleMsg( msg, mp1, mp2);
|
||||
else
|
||||
mRet = WinDefWindowProc( h, msg, mp1, mp2);
|
||||
return mRet;
|
||||
}
|
||||
|
||||
// Recycling management
|
||||
nsTimer *nsTimerManager::CreateTimer()
|
||||
{
|
||||
nsTimer *rc;
|
||||
if( !mBase)
|
||||
{
|
||||
rc = new nsTimer( this);
|
||||
#ifdef PROFILE_TIMERS
|
||||
mPeak++;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = mBase;
|
||||
mBase = rc->mNext;
|
||||
rc->Construct();
|
||||
mSize--;
|
||||
}
|
||||
#ifdef PROFILE_TIMERS
|
||||
mCount++;
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
void nsTimerManager::DisposeTimer( nsTimer *aTimer)
|
||||
{
|
||||
if( TIMER_CACHESIZE == mSize)
|
||||
{
|
||||
delete aTimer;
|
||||
#ifdef PROFILE_TIMERS
|
||||
mDeleted++;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
aTimer->Destruct();
|
||||
aTimer->mNext = mBase;
|
||||
mBase = aTimer;
|
||||
mSize++;
|
||||
}
|
||||
}
|
||||
|
||||
// Complicated functions to maintain the list of timers.
|
||||
// This code has something of a pedigree -- I worked it through once,
|
||||
// ages ago, for os2fe, and convinced myself it was correct.
|
||||
|
||||
// Adjust the period of the window timer according to the contents of
|
||||
// the timer list, and record the absolute time that the next firing
|
||||
// will occur. May well stop the window timer entirely.
|
||||
void nsTimerManager::SyncTimeoutPeriod( ULONG aTickCount)
|
||||
{
|
||||
// May want us to set tick count ourselves.
|
||||
if( 0 == aTickCount)
|
||||
aTickCount = WinGetCurrentTime( 0/*hab*/);
|
||||
|
||||
// If there's no list, we should clear the timer.
|
||||
if( !mTimerList)
|
||||
{
|
||||
if( mTimerSet)
|
||||
{
|
||||
StopTimer();
|
||||
mNextFire = TIMEOUT_NEVER;
|
||||
mTimerSet = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// See if we need to clear the current timer.
|
||||
// Circumstances are that if the timer will not
|
||||
// fire on time for the next timeout.
|
||||
BOOL bSetTimer = FALSE;
|
||||
nsTimer *pTimeout = mTimerList;
|
||||
if( mTimerSet)
|
||||
{
|
||||
if( pTimeout->mFireTime != mNextFire)
|
||||
{
|
||||
StopTimer();
|
||||
mNextFire = TIMEOUT_NEVER;
|
||||
mTimerSet = FALSE;
|
||||
|
||||
// Set the timer.
|
||||
bSetTimer = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No timer set, attempt.
|
||||
bSetTimer = TRUE;
|
||||
}
|
||||
|
||||
if( bSetTimer)
|
||||
{
|
||||
ULONG ulFireWhen = pTimeout->mFireTime > aTickCount ?
|
||||
pTimeout->mFireTime - aTickCount : 0;
|
||||
if( ulFireWhen > UINT_MAX)
|
||||
ulFireWhen = UINT_MAX;
|
||||
|
||||
NS_ASSERTION(mTimerSet == FALSE,"logic error in timer sync magic");
|
||||
StartTimer( ulFireWhen);
|
||||
|
||||
// Set the fire time.
|
||||
mNextFire = pTimeout->mFireTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Walk down the timeout list and fire those which are due.
|
||||
void nsTimerManager::ProcessTimeouts( ULONG aNow)
|
||||
{
|
||||
nsTimer *p = mTimerList;
|
||||
|
||||
if( 0 == aNow)
|
||||
aNow = WinGetCurrentTime( 0/*hab*/);
|
||||
|
||||
BOOL bCalledSync = FALSE;
|
||||
|
||||
// loop over all entries
|
||||
while( p)
|
||||
{
|
||||
// send it
|
||||
if( p->mFireTime < aNow)
|
||||
{
|
||||
// Fire it, making sure the timer doesn't die.
|
||||
NS_ADDREF(p);
|
||||
p->Fire( aNow);
|
||||
|
||||
// Clear the timer.
|
||||
// Period synced.
|
||||
p->Cancel();
|
||||
bCalledSync = TRUE;
|
||||
NS_RELEASE(p);
|
||||
|
||||
// Reset the loop (can't look at p->pNext now, and called
|
||||
// code may have added/cleared timers).
|
||||
// (could do this by going recursive and returning).
|
||||
p = mTimerList;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure we fire a timer.
|
||||
// Also, we need to check to see if things are backing up (they
|
||||
// may be asking to be fired long before we ever get to them,
|
||||
// and we don't want to pass in negative values to the real
|
||||
// timer code, or it takes days to fire....
|
||||
if( FALSE == bCalledSync)
|
||||
{
|
||||
SyncTimeoutPeriod( aNow);
|
||||
bCalledSync = TRUE;
|
||||
}
|
||||
// Get next timer.
|
||||
p = p->mNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init a timer - insert it into the list, adjust the window timer to be
|
||||
// running fast enough to make sure it fires when it should.
|
||||
nsresult nsTimerManager::InitTimer( nsTimer *aTimer, PRUint32 aDelay)
|
||||
{
|
||||
#ifdef VERIFY_THREADS
|
||||
if( aTimer->mTID != QueryCurrentTID())
|
||||
printf( "*** Thread assumption violated in base/src/os2/nsTimerOS2.cpp\n");
|
||||
#endif
|
||||
|
||||
ULONG ulNow = WinGetCurrentTime( 0/*hab*/);
|
||||
|
||||
aTimer->mDelay = aDelay;
|
||||
aTimer->mFireTime = (ULONG) aDelay + ulNow;
|
||||
aTimer->mNext = nsnull;
|
||||
|
||||
// add it to the list
|
||||
if( !mTimerList)
|
||||
mTimerList = aTimer;
|
||||
else
|
||||
{
|
||||
// is it before everything else on the list?
|
||||
if( aTimer->mFireTime < mTimerList->mFireTime)
|
||||
{
|
||||
aTimer->mNext = mTimerList;
|
||||
mTimerList = aTimer;
|
||||
}
|
||||
else
|
||||
{
|
||||
nsTimer *pPrev = mTimerList;
|
||||
nsTimer *pCurrent = mTimerList;
|
||||
|
||||
while( pCurrent &&
|
||||
(pCurrent->mFireTime <= aTimer->mFireTime))
|
||||
{
|
||||
pPrev = pCurrent;
|
||||
pCurrent = pCurrent->mNext;
|
||||
}
|
||||
|
||||
NS_ASSERTION(pPrev,"logic error in InitTimer");
|
||||
|
||||
// insert it after pPrev (this could be at the end of the list)
|
||||
aTimer->mNext = pPrev->mNext;
|
||||
pPrev->mNext = aTimer;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PROFILE_TIMERS
|
||||
mActive++;
|
||||
#endif
|
||||
|
||||
// Sync the timer fire period.
|
||||
SyncTimeoutPeriod( ulNow);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Cancel a timer - remove it from the list, adjust the window timer as
|
||||
// appropriate.
|
||||
void nsTimerManager::CancelTimer( nsTimer *aTimer)
|
||||
{
|
||||
if( mTimerList == aTimer)
|
||||
{
|
||||
// first element in the list lossage
|
||||
mTimerList = aTimer->mNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
// walk until no next pointer
|
||||
nsTimer *p = mTimerList;
|
||||
while( p && p->mNext && (p->mNext != aTimer))
|
||||
p = p->mNext;
|
||||
|
||||
// if we found something valid pull it out of the list
|
||||
if( p && p->mNext && p->mNext == aTimer)
|
||||
{
|
||||
p->mNext = aTimer->mNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we come here at app-shutdown/crash when timers which are still in the
|
||||
// active-timer list are deleted.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PROFILE_TIMERS
|
||||
mActive--;
|
||||
#endif
|
||||
|
||||
// Adjust window timer
|
||||
SyncTimeoutPeriod( 0);
|
||||
}
|
||||
|
||||
// Data structure to hold and create nsTimerManagers.
|
||||
// This is (meant to be) thread-safe.
|
||||
class nsTimerManagers
|
||||
{
|
||||
nsHashtable mTable;
|
||||
HMTX mMutex;
|
||||
|
||||
struct TIDKey : public nsVoidKey
|
||||
{
|
||||
TIDKey() : nsVoidKey((void*)QueryCurrentTID())
|
||||
{}
|
||||
};
|
||||
|
||||
struct Lock
|
||||
{
|
||||
HMTX mHmtx;
|
||||
Lock( HMTX hmtx) : mHmtx(hmtx)
|
||||
{
|
||||
DosRequestMutexSem( mHmtx, SEM_INDEFINITE_WAIT);
|
||||
}
|
||||
~Lock()
|
||||
{
|
||||
DosReleaseMutexSem( mHmtx);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
nsTimerManagers() : mMutex(0)
|
||||
{
|
||||
DosCreateMutexSem( 0, &mMutex, 0, 0 /*unowned*/);
|
||||
}
|
||||
|
||||
static PRBool mgr_dtor( nsHashKey *aKey, void *aData, void */*aClosure*/)
|
||||
{
|
||||
nsTimerManager *pManager = (nsTimerManager*) aData;
|
||||
delete pManager;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
~nsTimerManagers()
|
||||
{
|
||||
mTable.Enumerate( &mgr_dtor);
|
||||
if( mMutex)
|
||||
DosCloseMutexSem( mMutex);
|
||||
}
|
||||
|
||||
nsTimerManager *Get()
|
||||
{
|
||||
Lock lock(mMutex);
|
||||
TIDKey key;
|
||||
|
||||
nsTimerManager *aMgr = (nsTimerManager*) mTable.Get( &key);
|
||||
|
||||
if( !aMgr)
|
||||
{
|
||||
aMgr = new nsTimerManager;
|
||||
mTable.Put( &key, aMgr);
|
||||
}
|
||||
|
||||
return aMgr;
|
||||
}
|
||||
|
||||
} TimerManagers;
|
||||
|
||||
// Entry into the DLL. No, I dunno why there's not a normal factory
|
||||
// for this either. Ease of use?
|
||||
|
||||
NS_TIMER nsresult NS_NewTimer( nsITimer **aInstance)
|
||||
{
|
||||
if( !aInstance)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Assumption: timers are created in the same thread they are to be
|
||||
// used in. This seems likely, but we shall see.
|
||||
// If things seem screwy, set the VERIFY_THREADS flag on this file.
|
||||
|
||||
nsTimer *timer = TimerManagers.Get()->CreateTimer();
|
||||
if( !timer)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return timer->QueryInterface( nsITimer::GetIID(), (void **) aInstance);
|
||||
}
|
||||
|
||||
TID QueryCurrentTID()
|
||||
{
|
||||
PTIB pTib = 0;
|
||||
PPIB pPib = 0;
|
||||
DosGetInfoBlocks( &pTib, &pPib);
|
||||
return pTib->tib_ptib2->tib2_ultid;
|
||||
}
|
|
@ -1,264 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#include "nsITimer.h"
|
||||
#include "nsITimerCallback.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prlog.h"
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <Pt.h>
|
||||
|
||||
static NS_DEFINE_IID(kITimerIID, NS_ITIMER_IID);
|
||||
|
||||
/* Use the Widget Debug log */
|
||||
extern PRLogModuleInfo *PhWidLog;
|
||||
|
||||
/*
|
||||
* Implementation of timers QNX/Neutrino timers.
|
||||
*/
|
||||
|
||||
class TimerImpl : public nsITimer {
|
||||
public:
|
||||
|
||||
public:
|
||||
TimerImpl();
|
||||
virtual ~TimerImpl();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual nsresult Init( nsTimerCallbackFunc aFunc, void *aClosure, PRUint32 aDelay );
|
||||
virtual nsresult Init( nsITimerCallback *aCallback, PRUint32 aDelay );
|
||||
virtual void Cancel();
|
||||
virtual PRUint32 GetDelay() { return mDelay; }
|
||||
virtual void SetDelay( PRUint32 aDelay ) { mDelay=aDelay; };
|
||||
virtual void* GetClosure() { return mClosure; }
|
||||
|
||||
static int TimerEventHandler( void *aData, pid_t aRcvId, void *aMsg, size_t aMsgLen );
|
||||
|
||||
private:
|
||||
|
||||
nsresult SetupTimer( PRUint32 aDelay );
|
||||
|
||||
PRUint32 mDelay;
|
||||
nsTimerCallbackFunc mFunc;
|
||||
void *mClosure;
|
||||
nsITimerCallback *mCallback;
|
||||
timer_t mTimerId;
|
||||
pid_t mPulsePid;
|
||||
PtPulseMsg_t mPulseMsg;
|
||||
PtPulseMsgId_t *mPulseMsgId;
|
||||
PtInputId_t *mInputId;
|
||||
};
|
||||
|
||||
|
||||
TimerImpl::TimerImpl()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mFunc = NULL;
|
||||
mClosure = NULL;
|
||||
mCallback = NULL;
|
||||
mDelay = 0;
|
||||
mTimerId = -1;
|
||||
mPulsePid = 0;
|
||||
mPulseMsgId = NULL;
|
||||
mInputId = NULL;
|
||||
}
|
||||
|
||||
|
||||
TimerImpl::~TimerImpl()
|
||||
{
|
||||
Cancel();
|
||||
NS_IF_RELEASE(mCallback);
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(TimerImpl, kITimerIID)
|
||||
|
||||
|
||||
NS_METHOD TimerImpl::SetupTimer( PRUint32 aDelay )
|
||||
{
|
||||
struct itimerspec tv;
|
||||
int err;
|
||||
|
||||
if ((aDelay > 10000) || (aDelay < 0))
|
||||
{
|
||||
NS_WARNING("TimerImpl::SetupTimer called with bogus value\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mDelay = aDelay;
|
||||
if( mPulsePid )
|
||||
{
|
||||
NS_ASSERTION(0,"TimerImpl::SetupTimer - reuse of timer not allowed!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if(( mPulsePid = PtAppCreatePulse( NULL, -1 )) > -2 )
|
||||
{
|
||||
NS_ASSERTION(0,"TimerImpl::SetupTimer - failed to create pulse");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if(( mPulseMsgId = PtPulseArmPid( NULL, mPulsePid, getpid(), &mPulseMsg )) == NULL )
|
||||
{
|
||||
NS_ASSERTION(0,"TimerImpl::SetupTimer - failed to arm pulse!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if(( mInputId = PtAppAddInput( NULL, mPulsePid, TimerEventHandler, this )) == NULL )
|
||||
{
|
||||
NS_ASSERTION(0,"TimerImpl::SetupTimer - failed to add input handler!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
err = timer_create( CLOCK_SOFTTIME, &mPulseMsg, &mTimerId );
|
||||
if( err != 0 )
|
||||
{
|
||||
NS_ASSERTION(0,"TimerImpl::SetupTimer - timer_create error");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
tv.it_interval.tv_sec = 0;
|
||||
tv.it_interval.tv_nsec = 0;
|
||||
tv.it_value.tv_sec = ( aDelay / 1000 );
|
||||
tv.it_value.tv_nsec = ( aDelay % 1000 ) * 1000000L;
|
||||
|
||||
/* If delay is set to 0 seconds then change it to 1 nsec. */
|
||||
if ( (tv.it_value.tv_sec == 0) && (tv.it_value.tv_nsec == 0))
|
||||
{
|
||||
tv.it_value.tv_nsec = 1;
|
||||
}
|
||||
|
||||
err = timer_settime( mTimerId, 0, &tv, 0 );
|
||||
if( err != 0 )
|
||||
{
|
||||
NS_ASSERTION(0,"TimerImpl::SetupTimer timer_settime");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_METHOD TimerImpl::Init( nsTimerCallbackFunc aFunc, void *aClosure, PRUint32 aDelay )
|
||||
{
|
||||
nsresult err;
|
||||
|
||||
mFunc = aFunc;
|
||||
mClosure = aClosure;
|
||||
err = SetupTimer( aDelay );
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
NS_METHOD TimerImpl::Init( nsITimerCallback *aCallback, PRUint32 aDelay )
|
||||
{
|
||||
nsresult err;
|
||||
|
||||
mCallback = aCallback;
|
||||
err = SetupTimer(aDelay);
|
||||
NS_ADDREF(mCallback);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void TimerImpl::Cancel()
|
||||
{
|
||||
int err;
|
||||
|
||||
if( mTimerId >= 0)
|
||||
{
|
||||
err = timer_delete( mTimerId );
|
||||
if (err < 0)
|
||||
{
|
||||
char buf[256];
|
||||
sprintf(buf, "TimerImpl::Cancel Failed in timer_delete mTimerId=<%d> err=<%d> errno=<%d>", mTimerId, err, errno);
|
||||
//NS_ASSERTION(0,"TimerImpl::Cancel Failed in timer_delete");
|
||||
NS_ASSERTION(0,buf);
|
||||
return;
|
||||
}
|
||||
|
||||
mTimerId *= -1; // HACK for Debug
|
||||
}
|
||||
|
||||
if( mInputId )
|
||||
{
|
||||
PtAppRemoveInput( NULL, mInputId );
|
||||
mInputId = NULL;
|
||||
}
|
||||
|
||||
if( mPulseMsgId )
|
||||
{
|
||||
PtPulseDisarm( mPulseMsgId );
|
||||
mPulseMsgId = NULL;
|
||||
}
|
||||
|
||||
if( mPulsePid )
|
||||
{
|
||||
PtAppDeletePulse( NULL, mPulsePid );
|
||||
mPulsePid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This is the timer handler that gets called by the Photon
|
||||
// input proc
|
||||
|
||||
int TimerImpl::TimerEventHandler( void *aData, pid_t aRcvId, void *aMsg, size_t aMsgLen )
|
||||
{
|
||||
int localTimerId;
|
||||
|
||||
TimerImpl* timer = (TimerImpl *)aData;
|
||||
if( timer )
|
||||
{
|
||||
localTimerId = timer->mTimerId;
|
||||
|
||||
if( timer->mFunc != NULL )
|
||||
{
|
||||
(*timer->mFunc)( timer, timer->mClosure );
|
||||
}
|
||||
else if ( timer->mCallback != NULL )
|
||||
{
|
||||
timer->mCallback->Notify( timer );
|
||||
}
|
||||
|
||||
/* These stupid people destroy this object inside the callback */
|
||||
/* so don't do anything with it from here on */
|
||||
}
|
||||
|
||||
return Pt_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
NS_TIMER nsresult NS_NewTimer(nsITimer** aInstancePtrResult)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "NS_NewTimer - null ptr");
|
||||
if (nsnull == aInstancePtrResult)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
TimerImpl *timer = new TimerImpl();
|
||||
if (nsnull == timer)
|
||||
{
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return timer->QueryInterface(kITimerIID, (void **) aInstancePtrResult);
|
||||
}
|
|
@ -1,200 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#include "nsITimer.h"
|
||||
#include "nsITimerCallback.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prlog.h"
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
//
|
||||
// Copied from the unix version, Rhapsody needs to
|
||||
// make this work. Stubs to compile things for now.
|
||||
//
|
||||
|
||||
#if 0
|
||||
Michael Hanni <mhanni@sprintmail.com> suggests:
|
||||
|
||||
I understand that nsTimer.cpp in base/rhapsody/ needs to be completed,
|
||||
yes? Wouldn't this code just use some NSTimers in the NSRunLoop?
|
||||
|
||||
Timer = [NSTimer timerWithTimeInterval:0.02 //seconds
|
||||
target:self
|
||||
selector:@selector(doThis:)
|
||||
userInfo:nil
|
||||
repeats:YES];
|
||||
[[NSRunLoop currentRunLoop] addTimer:Timer
|
||||
forMode:NSDefaultRunLoopMode];
|
||||
|
||||
I only looked at nsTimer.cpp briefly, but could something like this work
|
||||
if imbedded in all that c++? ;-)
|
||||
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_IID(kITimerIID, NS_ITIMER_IID);
|
||||
|
||||
extern void nsTimerExpired(void *aCallData);
|
||||
|
||||
class TimerImpl : public nsITimer {
|
||||
public:
|
||||
|
||||
public:
|
||||
TimerImpl();
|
||||
virtual ~TimerImpl();
|
||||
|
||||
virtual nsresult Init(nsTimerCallbackFunc aFunc,
|
||||
void *aClosure,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay);
|
||||
|
||||
virtual nsresult Init(nsITimerCallback *aCallback,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual void Cancel();
|
||||
virtual PRUint32 GetDelay() { return mDelay; }
|
||||
virtual void SetDelay(PRUint32 aDelay) { mDelay=aDelay; };
|
||||
virtual void* GetClosure() { return mClosure; }
|
||||
|
||||
void FireTimeout();
|
||||
|
||||
private:
|
||||
nsresult Init(PRUint32 aDelay);
|
||||
|
||||
PRUint32 mDelay;
|
||||
nsTimerCallbackFunc mFunc;
|
||||
void *mClosure;
|
||||
nsITimerCallback *mCallback;
|
||||
// PRBool mRepeat;
|
||||
TimerImpl *mNext;
|
||||
int mTimerId;
|
||||
};
|
||||
|
||||
void TimerImpl::FireTimeout()
|
||||
{
|
||||
if (mFunc != NULL) {
|
||||
(*mFunc)(this, mClosure);
|
||||
}
|
||||
else if (mCallback != NULL) {
|
||||
mCallback->Notify(this); // Fire the timer
|
||||
}
|
||||
|
||||
// Always repeating here
|
||||
|
||||
// if (mRepeat)
|
||||
// mTimerId = XtAppAddTimeOut(gAppContext, GetDelay(),(XtTimerCallbackProc)nsTimerExpired, this);
|
||||
}
|
||||
|
||||
|
||||
TimerImpl::TimerImpl()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mFunc = NULL;
|
||||
mCallback = NULL;
|
||||
mNext = NULL;
|
||||
mTimerId = 0;
|
||||
mDelay = 0;
|
||||
mClosure = NULL;
|
||||
}
|
||||
|
||||
TimerImpl::~TimerImpl()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
TimerImpl::Init(nsTimerCallbackFunc aFunc,
|
||||
void *aClosure,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay)
|
||||
{
|
||||
mFunc = aFunc;
|
||||
mClosure = aClosure;
|
||||
// mRepeat = aRepeat;
|
||||
|
||||
printf("TimerImpl::Init() not implemented\n");
|
||||
|
||||
#ifdef RHAPSODY_NEEDS_TO_IMPLEMENT_THIS
|
||||
mTimerId = XtAppAddTimeOut(gAppContext, aDelay,(XtTimerCallbackProc)nsTimerExpired, this);
|
||||
#endif
|
||||
|
||||
return Init(aDelay);
|
||||
}
|
||||
|
||||
nsresult
|
||||
TimerImpl::Init(nsITimerCallback *aCallback,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay)
|
||||
{
|
||||
mCallback = aCallback;
|
||||
// mRepeat = aRepeat;
|
||||
|
||||
printf("TimerImpl::Init() not implmented.\n");
|
||||
|
||||
#ifdef RHAPSODY_NEEDS_TO_IMPLEMENT_THIS
|
||||
mTimerId = XtAppAddTimeOut(gAppContext, aDelay, (XtTimerCallbackProc)nsTimerExpired, this);
|
||||
#endif
|
||||
|
||||
return Init(aDelay);
|
||||
}
|
||||
|
||||
nsresult
|
||||
TimerImpl::Init(PRUint32 aDelay)
|
||||
{
|
||||
mDelay = aDelay;
|
||||
NS_ADDREF(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(TimerImpl, kITimerIID)
|
||||
|
||||
|
||||
void
|
||||
TimerImpl::Cancel()
|
||||
{
|
||||
|
||||
printf("TimerImpl::Cancel() not implemented.\n");
|
||||
|
||||
#ifdef RHAPSODY_NEEDS_TO_IMPLEMENT_THIS
|
||||
XtRemoveTimeOut(mTimerId);
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_TIMER nsresult NS_NewTimer(nsITimer** aInstancePtrResult)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
TimerImpl *timer = new TimerImpl();
|
||||
if (nsnull == timer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return timer->QueryInterface(kITimerIID, (void **) aInstancePtrResult);
|
||||
}
|
||||
|
||||
|
||||
void nsTimerExpired(void *aCallData)
|
||||
{
|
||||
TimerImpl* timer = (TimerImpl *)aCallData;
|
||||
timer->FireTimeout();
|
||||
}
|
|
@ -143,7 +143,7 @@ gint nsTimerExpired(gpointer aCallData)
|
|||
return 0;
|
||||
}
|
||||
|
||||
NS_TIMER nsresult NS_NewTimer(nsITimer** aInstancePtrResult)
|
||||
nsresult NS_NewTimer(nsITimer** aInstancePtrResult)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsTimerMotif.h"
|
||||
|
||||
// #include "nsITimerCallback.h"
|
||||
// #include "nsCRT.h"
|
||||
// #include "prlog.h"
|
||||
// #include <stdio.h>
|
||||
// #include <limits.h>
|
||||
// #include <X11/Intrinsic.h>
|
||||
|
||||
static NS_DEFINE_IID(kITimerIID, NS_ITIMER_IID);
|
||||
|
||||
// Hack for now. This is Bad because it creates a dependency between the widget
|
||||
// library and this library. This needs to be replaced with having code
|
||||
// to pass an interface which can be queried for the app context.
|
||||
XtAppContext gAppContext;
|
||||
|
||||
extern void nsTimerExpired(XtPointer aCallData);
|
||||
|
||||
|
||||
void nsTimerMotif::FireTimeout()
|
||||
{
|
||||
if (mFunc != NULL) {
|
||||
(*mFunc)(this, mClosure);
|
||||
}
|
||||
else if (mCallback != NULL) {
|
||||
mCallback->Notify(this); // Fire the timer
|
||||
}
|
||||
|
||||
// Always repeating here
|
||||
|
||||
// if (mRepeat)
|
||||
// mTimerId = XtAppAddTimeOut(gAppContext, GetDelay(),(XtTimerCallbackProc)nsTimerExpired, this);
|
||||
}
|
||||
|
||||
|
||||
nsTimerMotif::nsTimerMotif()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mFunc = NULL;
|
||||
mCallback = NULL;
|
||||
mNext = NULL;
|
||||
mTimerId = 0;
|
||||
mDelay = 0;
|
||||
mClosure = NULL;
|
||||
}
|
||||
|
||||
nsTimerMotif::~nsTimerMotif()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTimerMotif::Init(nsTimerCallbackFunc aFunc,
|
||||
void *aClosure,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay)
|
||||
{
|
||||
mFunc = aFunc;
|
||||
mClosure = aClosure;
|
||||
// mRepeat = aRepeat;
|
||||
|
||||
mTimerId = XtAppAddTimeOut(gAppContext, aDelay,(XtTimerCallbackProc)nsTimerExpired, this);
|
||||
|
||||
return Init(aDelay);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTimerMotif::Init(nsITimerCallback *aCallback,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay)
|
||||
{
|
||||
mCallback = aCallback;
|
||||
// mRepeat = aRepeat;
|
||||
|
||||
mTimerId = XtAppAddTimeOut(gAppContext, aDelay, (XtTimerCallbackProc)nsTimerExpired, this);
|
||||
|
||||
return Init(aDelay);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTimerMotif::Init(PRUint32 aDelay)
|
||||
{
|
||||
mDelay = aDelay;
|
||||
NS_ADDREF(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsTimerMotif, kITimerIID)
|
||||
|
||||
|
||||
void
|
||||
nsTimerMotif::Cancel()
|
||||
{
|
||||
XtRemoveTimeOut(mTimerId);
|
||||
}
|
||||
|
||||
void nsTimerExpired(XtPointer aCallData)
|
||||
{
|
||||
nsTimerMotif* timer = (nsTimerMotif *)aCallData;
|
||||
timer->FireTimeout();
|
||||
}
|
||||
|
||||
NS_TIMER nsresult NS_NewTimer(nsITimer** aInstancePtrResult)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsTimerMotif *timer = new nsTimerMotif();
|
||||
if (nsnull == timer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return timer->QueryInterface(kITimerIID, (void **) aInstancePtrResult);
|
||||
}
|
|
@ -1,254 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsTimerXlib.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "prlog.h"
|
||||
|
||||
static NS_DEFINE_IID(kITimerIID, NS_ITIMER_IID);
|
||||
|
||||
extern "C" int NS_TimeToNextTimeout(struct timeval *aTimer);
|
||||
extern "C" void NS_ProcessTimeouts(void);
|
||||
|
||||
nsTimerXlib *nsTimerXlib::gTimerList = NULL;
|
||||
struct timeval nsTimerXlib::gTimer = {0, 0};
|
||||
struct timeval nsTimerXlib::gNextFire = {0, 0};
|
||||
|
||||
nsTimerXlib::nsTimerXlib()
|
||||
{
|
||||
//printf("nsTimerXlib::nsTimerXlib (%p) called.\n",
|
||||
//this);
|
||||
NS_INIT_REFCNT();
|
||||
mFunc = NULL;
|
||||
mCallback = NULL;
|
||||
mNext = NULL;
|
||||
mClosure = NULL;
|
||||
}
|
||||
|
||||
nsTimerXlib::~nsTimerXlib()
|
||||
{
|
||||
//printf("nsTimerXlib::~nsTimerXlib (%p) called.\n",
|
||||
// this);
|
||||
Cancel();
|
||||
NS_IF_RELEASE(mCallback);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsTimerXlib, kITimerIID)
|
||||
|
||||
nsresult
|
||||
nsTimerXlib::Init(nsTimerCallbackFunc aFunc,
|
||||
void *aClosure,
|
||||
PRUint32 aDelay)
|
||||
{
|
||||
mFunc = aFunc;
|
||||
mClosure = aClosure;
|
||||
return Init(aDelay);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTimerXlib::Init(nsITimerCallback *aCallback,
|
||||
PRUint32 aDelay)
|
||||
{
|
||||
mCallback = aCallback;
|
||||
NS_ADDREF(mCallback);
|
||||
|
||||
return Init(aDelay);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTimerXlib::Init(PRUint32 aDelay)
|
||||
{
|
||||
struct timeval Now;
|
||||
// printf("nsTimerXlib::Init (%p) called with delay %d\n",
|
||||
//this, aDelay);
|
||||
// get the cuurent time
|
||||
gettimeofday(&Now, NULL);
|
||||
mFireTime.tv_sec = Now.tv_sec + (aDelay / 1000);
|
||||
mFireTime.tv_usec = Now.tv_usec + (aDelay * 1000);
|
||||
//printf("fire set to %ld / %ld\n",
|
||||
//mFireTime.tv_sec, mFireTime.tv_usec);
|
||||
// set the next pointer to nothing.
|
||||
mNext = NULL;
|
||||
// add ourself to the list
|
||||
if (!gTimerList) {
|
||||
// no list here. I'm the start!
|
||||
//printf("This is the beginning of the list..\n");
|
||||
gTimerList = this;
|
||||
}
|
||||
else {
|
||||
// is it before everything else on the list?
|
||||
if ((mFireTime.tv_sec < gTimerList->mFireTime.tv_sec) &&
|
||||
(mFireTime.tv_usec < gTimerList->mFireTime.tv_usec)) {
|
||||
// printf("This is before the head of the list...\n");
|
||||
mNext = gTimerList;
|
||||
gTimerList = this;
|
||||
}
|
||||
else {
|
||||
nsTimerXlib *pPrev = gTimerList;
|
||||
nsTimerXlib *pCurrent = gTimerList;
|
||||
while (pCurrent && ((pCurrent->mFireTime.tv_sec <= mFireTime.tv_sec) &&
|
||||
(pCurrent->mFireTime.tv_usec <= mFireTime.tv_usec))) {
|
||||
pPrev = pCurrent;
|
||||
pCurrent = pCurrent->mNext;
|
||||
}
|
||||
PR_ASSERT(pPrev);
|
||||
|
||||
// isnert it after pPrev ( this could be at the end of the list)
|
||||
mNext = pPrev->mNext;
|
||||
pPrev->mNext = this;
|
||||
}
|
||||
}
|
||||
NS_ADDREF(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsTimerXlib::Fire(struct timeval *aNow)
|
||||
{
|
||||
// printf("nsTimerXlib::Fire (%p) called at %ld / %ld\n",
|
||||
// this,
|
||||
//aNow->tv_sec, aNow->tv_usec);
|
||||
if (mFunc != NULL) {
|
||||
(*mFunc)(this, mClosure);
|
||||
}
|
||||
else if (mCallback != NULL) {
|
||||
mCallback->Notify(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTimerXlib::Cancel()
|
||||
{
|
||||
nsTimerXlib *me = this;
|
||||
nsTimerXlib *p;
|
||||
// printf("nsTimerXlib::Cancel (%p) called.\n",
|
||||
// this);
|
||||
if (gTimerList == this) {
|
||||
// first element in the list lossage...
|
||||
gTimerList = mNext;
|
||||
}
|
||||
else {
|
||||
// walk until there's no next pointer
|
||||
for (p = gTimerList; p && p->mNext && (p->mNext != this); p = p->mNext)
|
||||
;
|
||||
|
||||
// if we found something valid pull it out of the list
|
||||
if (p && p->mNext && p->mNext == this) {
|
||||
p->mNext = mNext;
|
||||
}
|
||||
else {
|
||||
// get out before we delete something that looks bogus
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if we got here it must have been a valid element so trash it
|
||||
NS_RELEASE(me);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
nsTimerXlib::ProcessTimeouts(struct timeval *aNow)
|
||||
{
|
||||
nsTimerXlib *p = gTimerList;
|
||||
if (aNow->tv_sec == 0 &&
|
||||
aNow->tv_usec == 0) {
|
||||
gettimeofday(aNow, NULL);
|
||||
}
|
||||
// printf("nsTimerXlib::ProcessTimeouts called at %ld / %ld\n",
|
||||
// aNow->tv_sec, aNow->tv_usec);
|
||||
while (p) {
|
||||
if ((p->mFireTime.tv_sec < aNow->tv_sec) ||
|
||||
((p->mFireTime.tv_sec == aNow->tv_sec) &&
|
||||
(p->mFireTime.tv_usec <= aNow->tv_usec))) {
|
||||
// Make sure that the timer cannot be deleted during the
|
||||
// Fire(...) call which may release *all* other references
|
||||
// to p...
|
||||
//printf("Firing timeout for (%p)\n",
|
||||
// p);
|
||||
NS_ADDREF(p);
|
||||
p->Fire(aNow);
|
||||
// Clear the timer.
|
||||
// Period synced.
|
||||
p->Cancel();
|
||||
NS_RELEASE(p);
|
||||
// Reset the loop (can't look at p->pNext now, and called
|
||||
// code may have added/cleared timers).
|
||||
// (could do this by going recursive and returning).
|
||||
p = gTimerList;
|
||||
}
|
||||
else {
|
||||
p = p->mNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int NS_TimeToNextTimeout(struct timeval *aTimer) {
|
||||
nsTimerXlib *timer;
|
||||
timer = nsTimerXlib::gTimerList;
|
||||
if (timer) {
|
||||
if ((timer->mFireTime.tv_sec < aTimer->tv_sec) ||
|
||||
((timer->mFireTime.tv_sec == aTimer->tv_sec) &&
|
||||
(timer->mFireTime.tv_usec <= aTimer->tv_usec))) {
|
||||
aTimer->tv_sec = 0;
|
||||
aTimer->tv_usec = 0;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
aTimer->tv_sec -= timer->mFireTime.tv_sec;
|
||||
// handle the overflow case
|
||||
if (aTimer->tv_usec < timer->mFireTime.tv_usec) {
|
||||
aTimer->tv_usec = timer->mFireTime.tv_usec - aTimer->tv_usec;
|
||||
// make sure we don't go past zero when we decrement
|
||||
if (aTimer->tv_sec)
|
||||
aTimer->tv_sec--;
|
||||
}
|
||||
else {
|
||||
aTimer->tv_usec -= timer->mFireTime.tv_usec;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void NS_ProcessTimeouts(void) {
|
||||
struct timeval now;
|
||||
now.tv_sec = 0;
|
||||
now.tv_usec = 0;
|
||||
nsTimerXlib::ProcessTimeouts(&now);
|
||||
}
|
||||
|
||||
NS_TIMER nsresult NS_NewTimer(nsITimer** aInstancePtrResult)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsTimerXlib *timer = new nsTimerXlib();
|
||||
if (nsnull == timer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return timer->QueryInterface(kITimerIID, (void **) aInstancePtrResult);
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..\..
|
||||
LIBRARY_NAME=timer_s
|
||||
|
||||
DEFINES=-D_IMPL_NS_TIMER -DWIN32_LEAN_AND_MEAN -DSTRICT
|
||||
|
||||
CPPSRCS = \
|
||||
nsTimer.cpp \
|
||||
$(NULL)
|
||||
|
||||
MODULE=timer
|
||||
|
||||
REQUIRES=xpcom
|
||||
|
||||
CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsTimer.obj \
|
||||
$(NULL)
|
||||
|
||||
LINCS= \
|
||||
-I..\
|
||||
-I$(PUBLIC)\xpcom \
|
||||
$(NULL)
|
||||
|
||||
LCFLAGS = \
|
||||
$(LCFLAGS) \
|
||||
$(DEFINES) \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
libs:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
rm -f $(PDBFILE).pdb
|
|
@ -1,362 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#include "nsITimer.h"
|
||||
#include "nsITimerCallback.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prlog.h"
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <limits.h>
|
||||
|
||||
static NS_DEFINE_IID(kITimerIID, NS_ITIMER_IID);
|
||||
|
||||
/*
|
||||
* Implementation of timers lifted from Windows front-end file timer.cpp
|
||||
*/
|
||||
class TimerImpl : public nsITimer {
|
||||
public:
|
||||
static TimerImpl *gTimerList;
|
||||
static UINT gWindowsTimer;
|
||||
static DWORD gNextFire;
|
||||
|
||||
static void ProcessTimeouts(DWORD aNow);
|
||||
static void SyncTimeoutPeriod(DWORD aTickCount);
|
||||
|
||||
public:
|
||||
TimerImpl();
|
||||
virtual ~TimerImpl();
|
||||
|
||||
virtual nsresult Init(nsTimerCallbackFunc aFunc,
|
||||
void *aClosure,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay);
|
||||
|
||||
virtual nsresult Init(nsITimerCallback *aCallback,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual void Cancel();
|
||||
void Fire(DWORD aNow);
|
||||
|
||||
virtual PRUint32 GetDelay() { return mDelay; }
|
||||
virtual void SetDelay(PRUint32 aDelay) {};
|
||||
|
||||
virtual void* GetClosure() { return mClosure; }
|
||||
|
||||
private:
|
||||
nsresult Init(PRUint32 aDelay);
|
||||
|
||||
PRUint32 mDelay;
|
||||
nsTimerCallbackFunc mFunc;
|
||||
void *mClosure;
|
||||
nsITimerCallback *mCallback;
|
||||
DWORD mFireTime;
|
||||
// PRBool mRepeat;
|
||||
TimerImpl *mNext;
|
||||
};
|
||||
|
||||
TimerImpl *TimerImpl::gTimerList = NULL;
|
||||
UINT TimerImpl::gWindowsTimer = 0;
|
||||
DWORD TimerImpl::gNextFire = (DWORD)-1;
|
||||
|
||||
void CALLBACK FireTimeout(HWND aWindow,
|
||||
UINT aMessage,
|
||||
UINT aTimerID,
|
||||
DWORD aTime)
|
||||
{
|
||||
static BOOL bCanEnter = TRUE;
|
||||
|
||||
// Don't allow old timer messages in here.
|
||||
if(aMessage != WM_TIMER) {
|
||||
PR_ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(aTimerID != TimerImpl::gWindowsTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Block only one entry into this function, or else.
|
||||
if(bCanEnter) {
|
||||
bCanEnter = FALSE;
|
||||
// see if we need to fork off any timeout functions
|
||||
if(TimerImpl::gTimerList) {
|
||||
TimerImpl::ProcessTimeouts(aTime);
|
||||
}
|
||||
bCanEnter = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to correctly have the timer be set.
|
||||
void
|
||||
TimerImpl::SyncTimeoutPeriod(DWORD aTickCount)
|
||||
{
|
||||
// May want us to set tick count ourselves.
|
||||
if(aTickCount == 0) {
|
||||
aTickCount = ::GetTickCount();
|
||||
}
|
||||
|
||||
// If there's no list, we should clear the timer.
|
||||
if(!gTimerList) {
|
||||
if(gWindowsTimer) {
|
||||
::KillTimer(NULL, gWindowsTimer);
|
||||
gWindowsTimer = 0;
|
||||
gNextFire = (DWORD)-1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// See if we need to clear the current timer.
|
||||
// Curcumstances are that if the timer will not
|
||||
// fire on time for the next timeout.
|
||||
BOOL bSetTimer = FALSE;
|
||||
TimerImpl *pTimeout = gTimerList;
|
||||
if(gWindowsTimer) {
|
||||
if(pTimeout->mFireTime != gNextFire) {
|
||||
::KillTimer(NULL, gWindowsTimer);
|
||||
gWindowsTimer = 0;
|
||||
gNextFire = (DWORD)-1;
|
||||
|
||||
// Set the timer.
|
||||
bSetTimer = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No timer set, attempt.
|
||||
bSetTimer = TRUE;
|
||||
}
|
||||
|
||||
if(bSetTimer) {
|
||||
DWORD dwFireWhen = pTimeout->mFireTime > aTickCount ?
|
||||
pTimeout->mFireTime - aTickCount : 0;
|
||||
if(dwFireWhen > UINT_MAX) {
|
||||
dwFireWhen = UINT_MAX;
|
||||
}
|
||||
UINT uFireWhen = (UINT)dwFireWhen;
|
||||
|
||||
PR_ASSERT(gWindowsTimer == 0);
|
||||
gWindowsTimer = ::SetTimer(NULL, 0, uFireWhen, (TIMERPROC)FireTimeout);
|
||||
|
||||
if(gWindowsTimer) {
|
||||
// Set the fire time.
|
||||
gNextFire = pTimeout->mFireTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Walk down the timeout list and launch anyone appropriate
|
||||
void
|
||||
TimerImpl::ProcessTimeouts(DWORD aNow)
|
||||
{
|
||||
TimerImpl *p = gTimerList;
|
||||
if(aNow == 0) {
|
||||
aNow = ::GetTickCount();
|
||||
}
|
||||
|
||||
BOOL bCalledSync = FALSE;
|
||||
|
||||
// loop over all entries
|
||||
while(p) {
|
||||
// send it
|
||||
if(p->mFireTime < aNow) {
|
||||
// Make sure that the timer cannot be deleted during the
|
||||
// Fire(...) call which may release *all* other references
|
||||
// to p...
|
||||
NS_ADDREF(p);
|
||||
p->Fire(aNow);
|
||||
|
||||
// Clear the timer.
|
||||
// Period synced.
|
||||
p->Cancel();
|
||||
bCalledSync = TRUE;
|
||||
NS_RELEASE(p);
|
||||
|
||||
// Reset the loop (can't look at p->pNext now, and called
|
||||
// code may have added/cleared timers).
|
||||
// (could do this by going recursive and returning).
|
||||
p = gTimerList;
|
||||
} else {
|
||||
// Make sure we fire an timer.
|
||||
// Also, we need to check to see if things are backing up (they
|
||||
// may be asking to be fired long before we ever get to them,
|
||||
// and we don't want to pass in negative values to the real
|
||||
// timer code, or it takes days to fire....
|
||||
if(bCalledSync == FALSE) {
|
||||
SyncTimeoutPeriod(aNow);
|
||||
bCalledSync = TRUE;
|
||||
}
|
||||
// Get next timer.
|
||||
p = p->mNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TimerImpl::TimerImpl()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mFunc = NULL;
|
||||
mCallback = NULL;
|
||||
mNext = NULL;
|
||||
mClosure = nsnull;
|
||||
}
|
||||
|
||||
TimerImpl::~TimerImpl()
|
||||
{
|
||||
Cancel();
|
||||
NS_IF_RELEASE(mCallback);
|
||||
}
|
||||
|
||||
nsresult
|
||||
TimerImpl::Init(nsTimerCallbackFunc aFunc,
|
||||
void *aClosure,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay)
|
||||
{
|
||||
mFunc = aFunc;
|
||||
mClosure = aClosure;
|
||||
// mRepeat = aRepeat;
|
||||
|
||||
return Init(aDelay);
|
||||
}
|
||||
|
||||
nsresult
|
||||
TimerImpl::Init(nsITimerCallback *aCallback,
|
||||
// PRBool aRepeat,
|
||||
PRUint32 aDelay)
|
||||
{
|
||||
mCallback = aCallback;
|
||||
NS_ADDREF(mCallback);
|
||||
// mRepeat = aRepeat;
|
||||
|
||||
return Init(aDelay);
|
||||
}
|
||||
|
||||
nsresult
|
||||
TimerImpl::Init(PRUint32 aDelay)
|
||||
{
|
||||
DWORD dwNow = ::GetTickCount();
|
||||
|
||||
mDelay = aDelay;
|
||||
mFireTime = (DWORD) aDelay + dwNow;
|
||||
mNext = NULL;
|
||||
|
||||
// add it to the list
|
||||
if(!gTimerList) {
|
||||
// no list add it
|
||||
gTimerList = this;
|
||||
}
|
||||
else {
|
||||
|
||||
// is it before everything else on the list?
|
||||
if(mFireTime < gTimerList->mFireTime) {
|
||||
|
||||
mNext = gTimerList;
|
||||
gTimerList = this;
|
||||
|
||||
} else {
|
||||
|
||||
TimerImpl * pPrev = gTimerList;
|
||||
TimerImpl * pCurrent = gTimerList;
|
||||
|
||||
while(pCurrent && (pCurrent->mFireTime <= mFireTime)) {
|
||||
pPrev = pCurrent;
|
||||
pCurrent = pCurrent->mNext;
|
||||
}
|
||||
|
||||
PR_ASSERT(pPrev);
|
||||
|
||||
// insert it after pPrev (this could be at the end of the list)
|
||||
mNext = pPrev->mNext;
|
||||
pPrev->mNext = this;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NS_ADDREF(this);
|
||||
|
||||
// Sync the timer fire period.
|
||||
SyncTimeoutPeriod(dwNow);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(TimerImpl, kITimerIID)
|
||||
|
||||
void
|
||||
TimerImpl::Fire(DWORD aNow)
|
||||
{
|
||||
if (mFunc != NULL) {
|
||||
(*mFunc)(this, mClosure);
|
||||
}
|
||||
else if (mCallback != NULL) {
|
||||
mCallback->Notify(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimerImpl::Cancel()
|
||||
{
|
||||
TimerImpl *me = this;
|
||||
|
||||
if(gTimerList == this) {
|
||||
|
||||
// first element in the list lossage
|
||||
gTimerList = mNext;
|
||||
|
||||
} else {
|
||||
|
||||
// walk until no next pointer
|
||||
for(TimerImpl * p = gTimerList; p && p->mNext && (p->mNext != this); p = p->mNext)
|
||||
;
|
||||
|
||||
// if we found something valid pull it out of the list
|
||||
if(p && p->mNext && p->mNext == this) {
|
||||
p->mNext = mNext;
|
||||
|
||||
} else {
|
||||
// get out before we delete something that looks bogus
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if we got here it must have been a valid element so trash it
|
||||
NS_RELEASE(me);
|
||||
|
||||
// If there's now no be sure to clear the timer.
|
||||
SyncTimeoutPeriod(0);
|
||||
}
|
||||
|
||||
NS_TIMER nsresult NS_NewTimer(nsITimer** aInstancePtrResult)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
TimerImpl *timer = new TimerImpl();
|
||||
if (nsnull == timer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return timer->QueryInterface(kITimerIID, (void **) aInstancePtrResult);
|
||||
}
|
|
@ -47,6 +47,7 @@ LCFLAGS = \
|
|||
LLIBS= \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(DIST)\lib\raptorgfxwin.lib \
|
||||
$(DIST)\lib\timer_s.lib \
|
||||
$(LIBNSPR)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
|
|
@ -73,6 +73,7 @@ LCFLAGS = \
|
|||
LLIBS= \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(DIST)\lib\raptorgfxwin.lib \
|
||||
$(DIST)\lib\timer_s.lib \
|
||||
$(DIST)\lib\img32$(VERSION_NUMBER).lib \
|
||||
$(DIST)\lib\util.lib \
|
||||
$(DIST)\lib\jsdom.lib \
|
||||
|
|
|
@ -79,6 +79,7 @@ LINCS= \
|
|||
|
||||
LLIBS= \
|
||||
$(DIST)\lib\raptorgfxwin.lib \
|
||||
$(DIST)\lib\timer_s.lib \
|
||||
$(DIST)\lib\raptorhtml.lib \
|
||||
$(DIST)\lib\raptorweb.lib \
|
||||
$(DIST)\lib\raptorwidget.lib \
|
||||
|
|
|
@ -134,12 +134,6 @@ typedef PRUint16 PRUnichar;
|
|||
#define NS_GFX_(type) NS_IMPORT_(type)
|
||||
#endif
|
||||
|
||||
#ifdef _IMPL_NS_TIMER
|
||||
#define NS_TIMER NS_EXPORT
|
||||
#else
|
||||
#define NS_TIMER NS_IMPORT
|
||||
#endif
|
||||
|
||||
#ifdef _IMPL_NS_PLUGIN
|
||||
#define NS_PLUGIN NS_EXPORT
|
||||
#else
|
||||
|
|
Загрузка…
Ссылка в новой задаче