Clean up BeOS timers. Among other things there now is a single thread to do

the job. Also I now cache the references to the native GUI queue, burning
fewer CPU cycles. Thanks to Attila Lendvai <101@inf.bme.hu> for contributions
and ideas.
This commit is contained in:
duncan%be.com 1999-07-15 15:32:44 +00:00
Родитель f135856aa7
Коммит f9dd72d087
6 изменённых файлов: 8 добавлений и 209 удалений

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

@ -1,191 +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 <Message.h>
#include "nsTimer.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;
}
void TimerImpl::FireTimeout()
{
if(! canceled)
{
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 = NULL;
mCallback = NULL;
mNext = NULL;
mDelay = 0;
mClosure = NULL;
sleepsem = B_ERROR;
canceled = false;
}
TimerImpl::~TimerImpl()
{
Cancel();
}
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;
// mRepeat = aRepeat;
return Init(aDelay);
}
nsresult
TimerImpl::Init(PRUint32 aDelay)
{
mDelay = aDelay;
NS_ADDREF(this); // this is for clients of the timer
mThread = PR_GetCurrentThread();
sleepsem = create_sem(0, "sleep sem");
mThreadID = spawn_thread(Sleepy, "Mozilla Timer", B_URGENT_DISPLAY_PRIORITY, this);
if(mThreadID > 0)
{
NS_ADDREF(this); // this is for the timer thread
resume_thread(mThreadID);
return NS_OK;
}
else
return NS_ERROR_FAILURE;
}
NS_IMPL_ISUPPORTS(TimerImpl, kITimerIID)
void
TimerImpl::Cancel()
{
delete_sem(sleepsem);
sleepsem = B_ERROR;
canceled = true;
}
long TimerImpl::Sleepy( void *args )
{
TimerImpl *tobj = (TimerImpl *)args;
char portname[64];
char semname[64];
sprintf(portname, "event%lx", tobj->mThread);
sprintf(semname, "sync%lx", tobj->mThread);
port_id eventport = find_port(portname);
sem_id syncsem = my_find_sem(semname);
bigtime_t sleeptime = (long long)(tobj->mDelay) * 1000L;
if(sleeptime == 0) sleeptime = 10;
if(acquire_sem_etc(tobj->sleepsem, 1, B_TIMEOUT, sleeptime) == B_TIMED_OUT)
{
// call timer synchronously so we're sure tobj is alive
ThreadInterfaceData id;
id.data = tobj;
id.sync = true;
if(write_port(eventport, WM_TIMER, &id, sizeof(id)) == B_OK)
while(acquire_sem(syncsem) == B_INTERRUPTED)
;
}
delete_sem(tobj->sleepsem);
tobj->sleepsem = B_ERROR;
NS_RELEASE(tobj);
return 0;
}
NS_BASE 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();
}

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

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

@ -33,7 +33,7 @@ REQUIRES=util img xpcom raptor netlib
DEFINES += -D_IMPL_NS_WIDGET
INCLUDES+= -I$(srcdir)/../xpwidgets -I$(srcdir)/. -I@top_srcdir@/gfx/src/beos
INCLUDES+= -I$(srcdir)/../xpwidgets -I$(srcdir)/.
INCLUDES += $(TK_CFLAGS)

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

@ -21,7 +21,6 @@
#include "nsIAppShell.h"
#include "nsWindow.h"
#include "nsSwitchToUIThread.h"
#include "nsTimer.h"
#include "plevent.h"
#include <stdlib.h>
@ -173,13 +172,9 @@ nsresult nsAppShell::Run()
{
switch(code)
{
case WM_TIMER :
{
TimerImpl *tobj = (TimerImpl *)id.data;
tobj->FireTimeout();
if(! id.sync)
NS_RELEASE(tobj);
}
case 'WMti' :
extern void nsTimerExpired(void *); // hack: this is in gfx
nsTimerExpired(id.data);
break;
case WM_CALLMETHOD :

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

@ -21,7 +21,6 @@
#include "prmon.h"
#include "prtime.h"
#include "nsITimer.h"
#include "nsTimer.h"
#include "nsGUIEvent.h"
#include "nsSwitchToUIThread.h"
#include "plevent.h"
@ -97,13 +96,9 @@ void nsToolkit::RunPump(void* arg)
{
switch(code)
{
case WM_TIMER :
{
TimerImpl *tobj = (TimerImpl *)id.data;
tobj->FireTimeout();
if(! id.sync)
NS_RELEASE(tobj);
}
case 'WMti' :
extern void nsTimerExpired(void *); // hack: this is in gfx
nsTimerExpired(id.data);
break;
case WM_CALLMETHOD :

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

@ -1105,7 +1105,7 @@ NS_METHOD nsWindow::Invalidate(PRBool aIsSynchronous)
if(mView && mView->LockLooper())
{
if(PR_TRUE == aIsSynchronous)
mView->Draw(mView->Bounds());
OnPaint(mBounds);
else
mView->Invalidate();
mView->UnlockLooper();