Checking in CFRunLoop patch in bug 271050 to test pageload performance in Camino. r=pinkerton

This commit is contained in:
smfr%smfr.org 2004-12-29 06:07:31 +00:00
parent d0064a3136
commit 726a1a4b01
2 changed files with 44 additions and 169 deletions

View File

@ -51,163 +51,11 @@
#undef DARWIN
#import <Cocoa/Cocoa.h>
//
// interface EventQueueHanlder
//
// An object that handles processing events for the PLEvent queue
// on each thread.
//
@interface EventQueueHandler : NSObject
{
nsIEventQueue* mMainThreadEventQueue; // addreffed
NSTimer* mEventTimer; // our timer [STRONG]
}
- (void)eventTimer:(NSTimer *)theTimer;
@end
static EventQueueHandler* gEventQueueHandler = nsnull;
@implementation EventQueueHandler
//
// -init
//
// Do init stuff. Cache the EventQueue Service and kick off our repeater
// to process PLEvents. The toolkit owns the timer so that neither Mozilla
// nor embedding apps need to worry about polling to process these events.
//
- (id)init
{
if ( (self = [super init]) )
{
nsCOMPtr<nsIEventQueueService> service = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID);
if (!service) {
[self release];
return nil;
}
service->GetThreadEventQueue(NS_CURRENT_THREAD, &mMainThreadEventQueue); // addref
mEventTimer = [NSTimer scheduledTimerWithTimeInterval:0.005
target:self
selector:@selector(eventTimer:)
userInfo:nil
repeats:YES];
if (!mMainThreadEventQueue || !mEventTimer) {
[self release];
return nil;
}
}
return self;
}
//
// -dealloc
//
// When we're finally ready to go away, kill our timer and get rid of the
// EventQueue Service. Also set the global var to null so in case we're called
// into action again we'll start over and not try to re-use the deleted object.
//
- (void) dealloc
{
[mEventTimer release];
NS_IF_RELEASE(mMainThreadEventQueue);
gEventQueueHandler = nsnull;
[super dealloc];
}
//
// -eventTimer
//
// Called periodically to process PLEvents from the queue on the current thread
//
#define MAX_PROCESS_EVENT_CALLS 20
//#define DEBUG_EVENT_TIMING
//#define TIMED_EVENT_PROCESSING
#define MAX_PLEVENT_TIME_MILLISECONDS 500
- (void)eventTimer:(NSTimer *)theTimer
{
#ifdef DEBUG_EVENT_TIMING
AbsoluteTime startTime = ::UpTime();
#endif
if (mMainThreadEventQueue)
{
#ifdef TIMED_EVENT_PROCESSING
// the new way; process events until some time has elapsed, or there are
// no events left. UpTime() is a very low-overhead way to measure time.
AbsoluteTime bailTime = ::AddDurationToAbsolute(MAX_PLEVENT_TIME_MILLISECONDS * durationMillisecond, ::UpTime());
while (1)
{
PRBool pendingEvents = PR_FALSE;
mMainThreadEventQueue->PendingEvents(&pendingEvents);
if (!pendingEvents)
break;
mMainThreadEventQueue->ProcessPendingEvents();
AbsoluteTime now = ::UpTime();
if (UnsignedWideToUInt64(now) > UnsignedWideToUInt64(bailTime))
break;
}
#else
// the old way; process events 20 times. Can suck CPU, and make the app
// unresponsive
for (PRInt32 i = 0; i < MAX_PROCESS_EVENT_CALLS; i ++)
{
PRBool pendingEvents = PR_FALSE;
mMainThreadEventQueue->PendingEvents(&pendingEvents);
if (!pendingEvents)
break;
mMainThreadEventQueue->ProcessPendingEvents();
}
#endif
}
#ifdef DEBUG_EVENT_TIMING
Nanoseconds duration = ::AbsoluteDeltaToNanoseconds(::UpTime(), startTime);
UInt32 milliseconds = UnsignedWideToUInt64(duration) / 1000000;
static UInt32 sMaxDuration = 0;
if (milliseconds > sMaxDuration)
sMaxDuration = milliseconds;
printf("Event handling took %u ms (max %u)\n", milliseconds, sMaxDuration);
#endif
}
@end
#pragma mark -
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
nsToolkit::nsToolkit()
{
if (!gEventQueueHandler)
{
// autorelease this so that if Init is never called, it is not
// leaked. Init retains it.
gEventQueueHandler = [[[EventQueueHandler alloc] init] autorelease];
}
}
//-------------------------------------------------------------------------
@ -215,13 +63,6 @@ nsToolkit::nsToolkit()
//-------------------------------------------------------------------------
nsToolkit::~nsToolkit()
{
/* Decrement our refcount on gEventQueueHandler; a prelude toward
stopping event handling. This is not something you want to do unless you've
bloody well started event handling and incremented the refcount. That's
done in the Init method, not the constructor, and that's what mInited is about.
*/
if (mInited && gEventQueueHandler)
[gEventQueueHandler release];
}
@ -231,11 +72,7 @@ nsToolkit::~nsToolkit()
nsresult
nsToolkit::InitEventQueue(PRThread * aThread)
{
if (!gEventQueueHandler)
return NS_ERROR_FAILURE;
[gEventQueueHandler retain];
// nothing to do
return NS_OK;
}

View File

@ -69,7 +69,10 @@
#endif
#if defined(XP_MAC) || defined(XP_MACOSX)
#if !defined(MOZ_WIDGET_COCOA) && TARGET_CARBON
#if defined(MOZ_WIDGET_COCOA)
#include <CoreFoundation/CoreFoundation.h>
#define MAC_USE_CFRUNLOOPSOURCE
#elif defined(TARGET_CARBON)
#include <CarbonEvents.h>
#define MAC_USE_CARBON_EVENT
#else
@ -169,7 +172,10 @@ struct PLEventQueue {
#elif defined(XP_BEOS)
port_id eventport;
#elif defined(XP_MAC) || defined(XP_MACOSX)
#if defined(MAC_USE_CARBON_EVENT)
#if defined(MAC_USE_CFRUNLOOPSOURCE)
CFRunLoopSourceRef mRunLoopSource;
CFRunLoopRef mMainRunLoop;
#elif defined(MAC_USE_CARBON_EVENT)
EventHandlerUPP eventHandlerUPP;
EventHandlerRef eventHandlerRef;
#elif defined(MAC_USE_WAKEUPPROCESS)
@ -984,6 +990,12 @@ _pl_CleanupNativeNotifier(PLEventQueue* self)
#elif defined(XP_OS2)
WinDestroyWindow(self->eventReceiverWindow);
#elif defined(MAC_USE_CFRUNLOOPSOURCE)
CFRunLoopRemoveSource(self->mMainRunLoop, self->mRunLoopSource, kCFRunLoopCommonModes);
CFRelease(self->mRunLoopSource);
CFRelease(self->mMainRunLoop);
#elif defined(MAC_USE_CARBON_EVENT)
EventComparatorUPP comparator = NewEventComparatorUPP(_md_CarbonEventComparator);
PR_ASSERT(comparator != NULL);
@ -1286,7 +1298,10 @@ _pl_NativeNotify(PLEventQueue* self)
static PRStatus
_pl_NativeNotify(PLEventQueue* self)
{
#if defined(MAC_USE_CARBON_EVENT)
#if defined(MAC_USE_CFRUNLOOPSOURCE)
CFRunLoopSourceSignal(self->mRunLoopSource);
CFRunLoopWakeUp(self->mMainRunLoop);
#elif defined(MAC_USE_CARBON_EVENT)
OSErr err;
EventRef newEvent;
if (CreateEvent(NULL, kEventClassPL, kEventProcessPLEvents,
@ -1600,7 +1615,14 @@ static void _md_CreateEventQueue( PLEventQueue *eventQueue )
} /* end _md_CreateEventQueue() */
#endif /* (defined(XP_UNIX) && !defined(XP_MACOSX)) || defined(XP_BEOS) */
#if defined(MAC_USE_CARBON_EVENT)
#if defined(MAC_USE_CFRUNLOOPSOURCE)
static void _md_EventReceiverProc(void *info)
{
PLEventQueue *queue = (PLEventQueue*)info;
PL_ProcessPendingEvents(queue);
}
#elif defined(MAC_USE_CARBON_EVENT)
/*
** _md_CreateEventQueue() -- ModelDependent initializer
*/
@ -1645,7 +1667,23 @@ static pascal Boolean _md_CarbonEventComparator(EventRef inEvent,
#if defined(XP_MAC) || defined(XP_MACOSX)
static void _md_CreateEventQueue( PLEventQueue *eventQueue )
{
#if defined(MAC_USE_CARBON_EVENT)
#if defined(MAC_USE_CFRUNLOOPSOURCE)
CFRunLoopSourceContext sourceContext = {0};
sourceContext.version = 0;
sourceContext.info = (void*)eventQueue;
sourceContext.perform = _md_EventReceiverProc;
// make a run loop source
eventQueue->mRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0 /* order */, &sourceContext);
PR_ASSERT(eventQueue->mRunLoopSource);
eventQueue->mMainRunLoop = CFRunLoopGetCurrent();
CFRetain(eventQueue->mMainRunLoop);
// and add it to the run loop.
CFRunLoopAddSource(eventQueue->mMainRunLoop, eventQueue->mRunLoopSource, kCFRunLoopCommonModes);
#elif defined(MAC_USE_CARBON_EVENT)
eventQueue->eventHandlerUPP = NewEventHandlerUPP(_md_EventReceiverProc);
PR_ASSERT(eventQueue->eventHandlerUPP);
if (eventQueue->eventHandlerUPP)