Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Enumerations | Functions | Variables
plevent.c File Reference
#include "nspr.h"
#include "plevent.h"
#include <errno.h>
#include <stddef.h>
#include <unistd.h>
#include "private/pprthred.h"

Go to the source code of this file.

Classes

struct  PLEventQueue

Defines

#define PR_EVENT_PTR(_qp)   ((PLEvent*) ((char*) (_qp) - offsetof(PLEvent, link)))

Enumerations

enum  EventQueueType { EventQueueIsNative = 1, EventQueueIsMonitored = 2 }

Functions

static PRStatus _pl_SetupNativeNotifier (PLEventQueue *self)
static void _pl_CleanupNativeNotifier (PLEventQueue *self)
static PRStatus _pl_NativeNotify (PLEventQueue *self)
static PRStatus _pl_AcknowledgeNativeNotify (PLEventQueue *self)
static void _md_CreateEventQueue (PLEventQueue *eventQueue)
static PRInt32 _pl_GetEventCount (PLEventQueue *self)
static PLEventQueue_pl_CreateEventQueue (const char *name, PRThread *handlerThread, EventQueueType qtype)
PLEventQueuePL_CreateEventQueue (const char *name, PRThread *handlerThread)
 PL_CreateNativeEventQueue (const char *name, PRThread *handlerThread)
 PL_CreateMonitoredEventQueue (const char *name, PRThread *handlerThread)
PRMonitorPL_GetEventQueueMonitor (PLEventQueue *self)
static void PR_CALLBACK _pl_destroyEvent (PLEvent *event, void *data, PLEventQueue *queue)
void PL_DestroyEventQueue (PLEventQueue *self)
PRStatus PL_PostEvent (PLEventQueue *self, PLEvent *event)
voidPL_PostSynchronousEvent (PLEventQueue *self, PLEvent *event)
PLEventPL_GetEvent (PLEventQueue *self)
PRBool PL_EventAvailable (PLEventQueue *self)
void PL_MapEvents (PLEventQueue *self, PLEventFunProc fun, void *data)
static void PR_CALLBACK _pl_DestroyEventForOwner (PLEvent *event, void *owner, PLEventQueue *queue)
void PL_RevokeEvents (PLEventQueue *self, void *owner)
void PL_ProcessPendingEvents (PLEventQueue *self)
void PL_InitEvent (PLEvent *self, void *owner, PLHandleEventProc handler, PLDestroyEventProc destructor)
voidPL_GetEventOwner (PLEvent *self)
void PL_HandleEvent (PLEvent *self)
void PL_DestroyEvent (PLEvent *self)
void PL_DequeueEvent (PLEvent *self, PLEventQueue *queue)
void PL_FavorPerformanceHint (PRBool favorPerformanceOverEventStarvation, PRUint32 starvationDelay)
PLEventPL_WaitForEvent (PLEventQueue *self)
void PL_EventLoop (PLEventQueue *self)
PRInt32 PL_GetEventQueueSelectFD (PLEventQueue *self)
PRBool PL_IsQueueOnCurrentThread (PLEventQueue *queue)
 PL_IsQueueNative (PLEventQueue *queue)

Variables

static PRLogModuleInfoevent_lm = NULL

Class Documentation

struct PLEventQueue

Definition at line 147 of file plevent.c.

Collaboration diagram for PLEventQueue:
Class Members
PRThread * handlerThread
PRMonitor * monitor
const char * name
PRPackedBool notified
PRPackedBool processingEvents
PRCList queue
EventQueueType type

Define Documentation

#define PR_EVENT_PTR (   _qp)    ((PLEvent*) ((char*) (_qp) - offsetof(PLEvent, link)))

Definition at line 183 of file plevent.c.


Enumeration Type Documentation

Enumerator:
EventQueueIsNative 
EventQueueIsMonitored 

Definition at line 141 of file plevent.c.


Function Documentation

static void _md_CreateEventQueue ( PLEventQueue eventQueue) [static]

Here is the caller graph for this function:

static PRStatus _pl_AcknowledgeNativeNotify ( PLEventQueue self) [static]

Definition at line 1306 of file plevent.c.

{
#if defined(_WIN32) || defined(XP_OS2)
#ifdef XP_OS2
    QMSG aMsg;
#else
    MSG aMsg;
#endif
    /*
     * only remove msg when we've been called directly by
     * PL_ProcessPendingEvents, not when we've been called by
     * the window proc because the window proc will remove the
     * msg for us.
     */
    if (self->removeMsg) {
        PR_LOG(event_lm, PR_LOG_DEBUG,
               ("_pl_AcknowledgeNativeNotify: self=%p", self));
#ifdef XP_OS2
        WinPeekMsg((HAB)0, &aMsg, self->eventReceiverWindow,
                   _pr_PostEventMsgId, _pr_PostEventMsgId, PM_REMOVE);
#else
        PeekMessage(&aMsg, self->eventReceiverWindow,
                    _pr_PostEventMsgId, _pr_PostEventMsgId, PM_REMOVE);
        if (self->timerSet) {
            KillTimer(self->eventReceiverWindow, TIMER_ID);
            self->timerSet = PR_FALSE;
        }
#endif
    }
    return PR_SUCCESS;
#elif defined(VMS)
    PR_LOG(event_lm, PR_LOG_DEBUG,
            ("_pl_AcknowledgeNativeNotify: self=%p efn=%d",
             self, self->efn));
    /*
    ** If this is the last entry, then clear the event flag. Also make sure
    ** the flag is cleared on any spurious wakeups.
    */
    sys$clref(self->efn);
    return PR_SUCCESS;
#elif defined(XP_UNIX) && !defined(XP_MACOSX)

    PRInt32 count;
    unsigned char c;
    PR_LOG(event_lm, PR_LOG_DEBUG,
            ("_pl_AcknowledgeNativeNotify: self=%p",
             self));
    /* consume the byte NativeNotify put in our pipe: */
    count = read(self->eventPipe[0], &c, 1);
    if ((count == 1) && (c == NOTIFY_TOKEN))
        return PR_SUCCESS;
    if ((count == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
        return PR_SUCCESS;
    return PR_FAILURE;
#else

    /* nothing to do on the other platforms */
    return PR_SUCCESS;
#endif
}

Here is the caller graph for this function:

static void _pl_CleanupNativeNotifier ( PLEventQueue self) [static]

Definition at line 945 of file plevent.c.

{
#if defined(VMS)
    {
        unsigned int status;
        PR_LOG(event_lm, PR_LOG_DEBUG,
           ("$$$ Freeing event flag %d", self->efn));
        status = LIB$FREE_EF(&self->efn);
    }
#elif defined(XP_UNIX) && !defined(XP_MACOSX)
    close(self->eventPipe[0]);
    close(self->eventPipe[1]);
#elif defined(_WIN32)
    if (self->timerSet) {
        KillTimer(self->eventReceiverWindow, TIMER_ID);
        self->timerSet = PR_FALSE;
    }
    RemoveProp(self->eventReceiverWindow, _md_GetEventQueuePropName());

    /* DestroyWindow doesn't do anything when called from a non ui thread.  Since 
     * self->eventReceiverWindow was created on the ui thread, it must be destroyed
     * on the ui thread.
     */
    SendMessage(self->eventReceiverWindow, WM_CLOSE, 0, 0);

#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);
    if (comparator) {
      FlushSpecificEventsFromQueue(GetMainEventQueue(), comparator, self);
      DisposeEventComparatorUPP(comparator);
    }
    DisposeEventHandlerUPP(self->eventHandlerUPP);
    RemoveEventHandler(self->eventHandlerRef);
#endif
}

Here is the caller graph for this function:

static PLEventQueue* _pl_CreateEventQueue ( const char *  name,
PRThread handlerThread,
EventQueueType  qtype 
) [static]

Definition at line 235 of file plevent.c.

{
    PRStatus err;
    PLEventQueue* self = NULL;
    PRMonitor* mon = NULL;

    if (event_lm == NULL)
        event_lm = PR_NewLogModule("event");

    self = PR_NEWZAP(PLEventQueue);
    if (self == NULL) return NULL;

    mon = PR_NewNamedMonitor(name);
    if (mon == NULL) goto error;

    self->name = name;
    self->monitor = mon;
    self->handlerThread = handlerThread;
    self->processingEvents = PR_FALSE;
    self->type = qtype;
#if defined(_WIN32)
    self->timerSet = PR_FALSE;
#endif
#if defined(_WIN32) || defined(XP_OS2)
    self->removeMsg = PR_TRUE;
#endif

    self->notified = PR_FALSE;

    PR_INIT_CLIST(&self->queue);
    if ( qtype == EventQueueIsNative ) {
        err = _pl_SetupNativeNotifier(self);
        if (err) goto error;
        _md_CreateEventQueue( self );
    }
    return self;

  error:
    if (mon != NULL)
        PR_DestroyMonitor(mon);
    PR_DELETE(self);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void PR_CALLBACK _pl_destroyEvent ( PLEvent event,
void data,
PLEventQueue queue 
) [static]

Definition at line 306 of file plevent.c.

{
    PL_DequeueEvent(event, queue);
    PL_DestroyEvent(event);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void PR_CALLBACK _pl_DestroyEventForOwner ( PLEvent event,
void owner,
PLEventQueue queue 
) [static]

Definition at line 511 of file plevent.c.

{
    PR_ASSERT(PR_GetMonitorEntryCount(queue->monitor) > 0);
    if (event->owner == owner) {
        PR_LOG(event_lm, PR_LOG_DEBUG,
               ("$$$ \tdestroying event %0x for owner %0x", event, owner));
        PL_DequeueEvent(event, queue);

        if (event->synchronousResult == (void*)PR_TRUE) {
            PR_Lock(event->lock);
            event->synchronousResult = NULL;
            event->handled = PR_TRUE;
            PR_NotifyCondVar(event->condVar);
            PR_Unlock(event->lock);
        }
        else {
            PL_DestroyEvent(event);
        }
    }
    else {
        PR_LOG(event_lm, PR_LOG_DEBUG,
               ("$$$ \tskipping event %0x for owner %0x", event, owner));
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRInt32 _pl_GetEventCount ( PLEventQueue self) [static]

Definition at line 575 of file plevent.c.

{
    PRCList* node;
    PRInt32  count = 0;

    PR_EnterMonitor(self->monitor);
    node = PR_LIST_HEAD(&self->queue);
    while (node != &self->queue) {
        count++;
        node = PR_NEXT_LINK(node);
    }
    PR_ExitMonitor(self->monitor);

    return count;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRStatus _pl_NativeNotify ( PLEventQueue self) [static]

Here is the caller graph for this function:

static PRStatus _pl_SetupNativeNotifier ( PLEventQueue self) [static]

Definition at line 844 of file plevent.c.

{
#if defined(VMS)
    unsigned int status;
    self->idFunc = 0;
    self->idFuncClosure = 0;
    status = LIB$GET_EF(&self->efn);
    if (!$VMS_STATUS_SUCCESS(status))
        return PR_FAILURE;
    PR_LOG(event_lm, PR_LOG_DEBUG,
           ("$$$ Allocated event flag %d", self->efn));
    return PR_SUCCESS;
#elif defined(XP_UNIX) && !defined(XP_MACOSX)
    int err;
    int flags;

    self->idFunc = 0;
    self->idFuncClosure = 0;

    err = pipe(self->eventPipe);
    if (err != 0) {
        return PR_FAILURE;
    }

    /* make the pipe nonblocking */
    flags = fcntl(self->eventPipe[0], F_GETFL, 0);
    if (flags == -1) {
        goto failed;
    }
    err = fcntl(self->eventPipe[0], F_SETFL, flags | O_NONBLOCK);
    if (err == -1) {
        goto failed;
    }
    flags = fcntl(self->eventPipe[1], F_GETFL, 0);
    if (flags == -1) {
        goto failed;
    }
    err = fcntl(self->eventPipe[1], F_SETFL, flags | O_NONBLOCK);
    if (err == -1) {
        goto failed;
    }
    return PR_SUCCESS;

failed:
    close(self->eventPipe[0]);
    close(self->eventPipe[1]);
    return PR_FAILURE;
#elif defined(XP_BEOS)
    /* hook up to the nsToolkit queue, however the appshell
     * isn't necessairly started, so we might have to create
     * the queue ourselves
     *
     * Set up the port for communicating. As restarts thru execv may occur
     * and ports survive those (with faulty events as result). Combined with the fact
     * that nsAppShell.cpp may or may not have created the port we need to take extra
     * care that the port is created for this launch, otherwise we need to reopen it
     * so that faulty messages gets lost.
     *
     * We do this by checking if the sem has been created. If it is we can reuse the port (if it exists).
     * Otherwise we need to create the sem and the port, deleting any open ports before.
     */
     
    sem_info info;
    int32 cookie = 0;

    char portname[64];
    char semname[64];
    PR_snprintf(portname, sizeof(portname), "event%lx", 
                (long unsigned) self->handlerThread);
    PR_snprintf(semname, sizeof(semname), "sync%lx", 
                (long unsigned) self->handlerThread);

    self->eventport = find_port(portname);
    while(get_next_sem_info(0, &cookie, &info) == B_OK)
    {
      if(strcmp(semname, info.name) != 0) {
        continue;
      }

      /* found semaphore */
      if(self->eventport < 0) {
        self->eventport = create_port(200, portname);
      }
      return PR_SUCCESS;
    }
    /* setup the port and semaphore */
    if(self->eventport >= 0) 
    {
      delete_port( self->eventport );
    }
    self->eventport = create_port(200, portname);
        /* We don't use the sem, but it has to be there
         */
        create_sem(0, semname);
    return PR_SUCCESS;
#else
    return PR_SUCCESS;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

PLEventQueue* PL_CreateEventQueue ( const char *  name,
PRThread handlerThread 
)

Definition at line 282 of file plevent.c.

{
    return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsNative ));
}

Here is the call graph for this function:

Here is the caller graph for this function:

PL_CreateMonitoredEventQueue ( const char *  name,
PRThread handlerThread 
)

Definition at line 294 of file plevent.c.

{
    return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsMonitored ));
}

Here is the call graph for this function:

PL_CreateNativeEventQueue ( const char *  name,
PRThread handlerThread 
)

Definition at line 288 of file plevent.c.

{
    return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsNative ));
}

Here is the call graph for this function:

void PL_DequeueEvent ( PLEvent self,
PLEventQueue queue 
)

Definition at line 731 of file plevent.c.

{
    if (self == NULL)
        return;

    /* Only the owner is allowed to dequeue events because once the
       client has put it in the queue, they have no idea whether it's
       been processed and destroyed or not. */

    PR_ASSERT(queue->handlerThread == PR_GetCurrentThread());

    PR_EnterMonitor(queue->monitor);

    PR_ASSERT(!PR_CLIST_IS_EMPTY(&self->link));

#if 0
    /*  I do not think that we need to do this anymore.
        if we do not acknowledge and this is the only
        only event in the queue, any calls to process
        the eventQ will be effective noop.
    */
    if (queue->type == EventQueueIsNative)
      _pl_AcknowledgeNativeNotify(queue);
#endif

    PR_REMOVE_AND_INIT_LINK(&self->link);

    PR_ExitMonitor(queue->monitor);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 708 of file plevent.c.

{
    if (self == NULL)
        return;

    /* This event better not be on an event queue anymore. */
    PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link));

    if(self->condVar)
      PR_DestroyCondVar(self->condVar);
    if(self->lock)
      PR_DestroyLock(self->lock);

#ifdef PL_POST_TIMINGS
    s_totalTime += PR_IntervalNow() - self->postTime;
    s_eventCount++;
    printf("$$$ running avg (%d) \n", PR_IntervalToMilliseconds(s_totalTime/s_eventCount));
#endif

    self->destructor(self);
}

Here is the call graph for this function:

Definition at line 313 of file plevent.c.

{
    PR_EnterMonitor(self->monitor);

    /* destroy undelivered events */
    PL_MapEvents(self, _pl_destroyEvent, NULL);

    if ( self->type == EventQueueIsNative )
        _pl_CleanupNativeNotifier(self);

    /* destroying the monitor also destroys the name */
    PR_ExitMonitor(self->monitor);
    PR_DestroyMonitor(self->monitor);
    PR_DELETE(self);

}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 476 of file plevent.c.

{
    PRBool result = PR_FALSE;

    if (self == NULL)
        return PR_FALSE;

    PR_EnterMonitor(self->monitor);

    if (!PR_CLIST_IS_EMPTY(&self->queue))
        result = PR_TRUE;

    PR_ExitMonitor(self->monitor);
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 818 of file plevent.c.

{
    if (self == NULL)
        return;

    while (PR_TRUE) {
        PLEvent* event = PL_WaitForEvent(self);
        if (event == NULL) {
            /* This can only happen if the current thread is interrupted */
            return;
        }

        PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event"));
        PL_HandleEvent(event);
        PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
    }
}

Here is the call graph for this function:

void PL_FavorPerformanceHint ( PRBool  favorPerformanceOverEventStarvation,
PRUint32  starvationDelay 
)

Definition at line 762 of file plevent.c.

{
#if defined(_WIN32)

    _md_StarvationDelay = starvationDelay;

    if (favorPerformanceOverEventStarvation) {
        _md_PerformanceSetting++;
        return;
    }

    _md_PerformanceSetting--;

    if (_md_PerformanceSetting == 0) {
      /* Switched from allowing event starvation to no event starvation so grab
         the current time to determine when to actually switch to using timers
         instead of posted WM_APP messages. */
      _md_SwitchTime = PR_IntervalToMilliseconds(PR_IntervalNow());
    }

#endif
}

Here is the caller graph for this function:

Definition at line 443 of file plevent.c.

{
    PLEvent* event = NULL;
    PRStatus err = PR_SUCCESS;

    if (self == NULL)
        return NULL;

    PR_EnterMonitor(self->monitor);

    if (!PR_CLIST_IS_EMPTY(&self->queue)) {
        if ( self->type == EventQueueIsNative &&
             self->notified                   &&
             !self->processingEvents          &&
             0 == _pl_GetEventCount(self)     )
        {
            err = _pl_AcknowledgeNativeNotify(self);
            self->notified = PR_FALSE;
        }
        if (err)
            goto done;

        /* then grab the event and return it: */
        event = PR_EVENT_PTR(self->queue.next);
        PR_REMOVE_AND_INIT_LINK(&event->link);
    }

  done:
    PR_ExitMonitor(self->monitor);
    return event;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 673 of file plevent.c.

{
    return self->owner;
}

Here is the caller graph for this function:

Definition at line 300 of file plevent.c.

{
    return self->monitor;
}

Definition at line 1368 of file plevent.c.

{
    if (self == NULL)
    return -1;

#if defined(VMS)
    return -(self->efn);
#elif defined(XP_UNIX) && !defined(XP_MACOSX)
    return self->eventPipe[0];
#else
    return -1;    /* other platforms don't handle this (yet) */
#endif
}

Definition at line 679 of file plevent.c.

{
    void* result;
    if (self == NULL)
        return;

    /* This event better not be on an event queue anymore. */
    PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link));

    result = self->handler(self);
    if (NULL != self->synchronousResult) {
        PR_Lock(self->lock);
        self->synchronousResult = result;
        self->handled = PR_TRUE;
        PR_NotifyCondVar(self->condVar);
        PR_Unlock(self->lock);
    }
    else {
        /* For asynchronous events, they're destroyed by the event-handler
           thread. See PR_PostSynchronousEvent. */
        PL_DestroyEvent(self);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PL_InitEvent ( PLEvent self,
void owner,
PLHandleEventProc  handler,
PLDestroyEventProc  destructor 
)

Definition at line 652 of file plevent.c.

{
#ifdef PL_POST_TIMINGS
    self->postTime = PR_IntervalNow();
#endif
    PR_INIT_CLIST(&self->link);
    self->handler = handler;
    self->destructor = destructor;
    self->owner = owner;
    self->synchronousResult = NULL;
    self->handled = PR_FALSE;
    self->lock = NULL;
    self->condVar = NULL;
#if defined(XP_UNIX) && !defined(XP_MACOSX)
    self->id = 0;
#endif
}

Definition at line 1390 of file plevent.c.

{
    return queue->type == EventQueueIsNative ? PR_TRUE : PR_FALSE;
}

Here is the caller graph for this function:

Definition at line 1383 of file plevent.c.

{
    PRThread *me = PR_GetCurrentThread();
    return me == queue->handlerThread;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PL_MapEvents ( PLEventQueue self,
PLEventFunProc  fun,
void data 
)

Definition at line 493 of file plevent.c.

{
    PRCList* qp;

    if (self == NULL)
        return;

    PR_EnterMonitor(self->monitor);
    qp = self->queue.next;
    while (qp != &self->queue) {
        PLEvent* event = PR_EVENT_PTR(qp);
        qp = qp->next;
        (*fun)(event, data, self);
    }
    PR_ExitMonitor(self->monitor);
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRStatus PL_PostEvent ( PLEventQueue self,
PLEvent event 
)

Definition at line 331 of file plevent.c.

{
    PRStatus err = PR_SUCCESS;
    PRMonitor* mon;

    if (self == NULL)
        return PR_FAILURE;

    mon = self->monitor;
    PR_EnterMonitor(mon);

#if defined(XP_UNIX) && !defined(XP_MACOSX)
    if (self->idFunc && event)
        event->id = self->idFunc(self->idFuncClosure);
#endif

    /* insert event into thread's event queue: */
    if (event != NULL) {
        PR_APPEND_LINK(&event->link, &self->queue);
    }

    if (self->type == EventQueueIsNative && !self->notified) {
        err = _pl_NativeNotify(self);

        if (err != PR_SUCCESS)
            goto error;

        self->notified = PR_TRUE;
    }

    /*
     * This may fall on deaf ears if we're really notifying the native
     * thread, and no one has called PL_WaitForEvent (or PL_EventLoop):
     */
    err = PR_Notify(mon);

error:
    PR_ExitMonitor(mon);
    return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* PL_PostSynchronousEvent ( PLEventQueue self,
PLEvent event 
)

Definition at line 373 of file plevent.c.

{
    void* result;

    if (self == NULL)
        return NULL;

    PR_ASSERT(event != NULL);

    if (PR_GetCurrentThread() == self->handlerThread) {
        /* Handle the case where the thread requesting the event handling
         * is also the thread that's supposed to do the handling. */
        result = event->handler(event);
    }
    else {
        int i, entryCount;

        event->lock = PR_NewLock();
        if (!event->lock) {
          return NULL;
        }
        event->condVar = PR_NewCondVar(event->lock);
        if(!event->condVar) {
          PR_DestroyLock(event->lock);
          event->lock = NULL;
          return NULL;
        }

        PR_Lock(event->lock);

        entryCount = PR_GetMonitorEntryCount(self->monitor);

        event->synchronousResult = (void*)PR_TRUE;

        PL_PostEvent(self, event);

        /* We need temporarily to give up our event queue monitor if
           we're holding it, otherwise, the thread we're going to wait
           for notification from won't be able to enter it to process
           the event. */
        if (entryCount) {
            for (i = 0; i < entryCount; i++)
                PR_ExitMonitor(self->monitor);
        }

        event->handled = PR_FALSE;

        while (!event->handled) {
            /* wait for event to be handled or destroyed */
            PR_WaitCondVar(event->condVar, PR_INTERVAL_NO_TIMEOUT);
        }

        if (entryCount) {
            for (i = 0; i < entryCount; i++)
                PR_EnterMonitor(self->monitor);
        }

        result = event->synchronousResult;
        event->synchronousResult = NULL;
        PR_Unlock(event->lock);
    }

    /* For synchronous events, they're destroyed here on the caller's
       thread before the result is returned. See PL_HandleEvent. */
    PL_DestroyEvent(event);

    return result;
}

Here is the call graph for this function:

Definition at line 592 of file plevent.c.

{
    PRInt32 count;

    if (self == NULL)
        return;


    PR_EnterMonitor(self->monitor);

    if (self->processingEvents) {
        _pl_AcknowledgeNativeNotify(self);
        self->notified = PR_FALSE;
        PR_ExitMonitor(self->monitor);
        return;
    }
    self->processingEvents = PR_TRUE;

    /* Only process the events that are already in the queue, and
     * not any new events that get added. Do this by counting the
     * number of events currently in the queue
     */
    count = _pl_GetEventCount(self);
    PR_ExitMonitor(self->monitor);

    while (count-- > 0) {
        PLEvent* event = PL_GetEvent(self);
        if (event == NULL)
            break;

        PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event"));
        PL_HandleEvent(event);
        PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
    }

    PR_EnterMonitor(self->monitor);

    if (self->type == EventQueueIsNative) {
        count = _pl_GetEventCount(self);

        if (count <= 0) {
            _pl_AcknowledgeNativeNotify(self);
            self->notified = PR_FALSE;
        }
        else {
            _pl_NativeNotify(self);
            self->notified = PR_TRUE;
        }

    }
    self->processingEvents = PR_FALSE;

    PR_ExitMonitor(self->monitor);
}

Here is the call graph for this function:

void PL_RevokeEvents ( PLEventQueue self,
void owner 
)

Definition at line 537 of file plevent.c.

{
    if (self == NULL)
        return;

    PR_LOG(event_lm, PR_LOG_DEBUG,
         ("$$$ revoking events for owner %0x", owner));

    /*
    ** First we enter the monitor so that no one else can post any events
    ** to the queue:
    */
    PR_EnterMonitor(self->monitor);
    PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ owner %0x, entered monitor", owner));

    /*
    ** Discard any pending events for this owner:
    */
    PL_MapEvents(self, _pl_DestroyEventForOwner, owner);

#ifdef DEBUG
    {
        PRCList* qp = self->queue.next;
        while (qp != &self->queue) {
            PLEvent* event = PR_EVENT_PTR(qp);
            qp = qp->next;
            PR_ASSERT(event->owner != owner);
        }
    }
#endif /* DEBUG */

    PR_ExitMonitor(self->monitor);

    PR_LOG(event_lm, PR_LOG_DEBUG,
           ("$$$ revoking events for owner %0x", owner));
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 794 of file plevent.c.

{
    PLEvent* event;
    PRMonitor* mon;

    if (self == NULL)
        return NULL;

    mon = self->monitor;
    PR_EnterMonitor(mon);

    while ((event = PL_GetEvent(self)) == NULL) {
        PRStatus err;
        PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ waiting for event"));
        err = PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
        if ((err == PR_FAILURE)
            && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break;
    }

    PR_ExitMonitor(mon);
    return event;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 131 of file plevent.c.