Back to index

lightning-sunbird  0.9+nobinonly
plevent.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org Code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /**********************************************************************
00039 NSPL Events
00040 
00041 Defining Events
00042 ---------------
00043 
00044 Events are essentially structures that represent argument lists for a
00045 function that will run on another thread. All event structures you
00046 define must include a PLEvent struct as their first field:
00047 
00048     typedef struct MyEventType {
00049         PLEvent      e;
00050               // arguments follow...
00051         int   x;
00052               char*  y;
00053     } MyEventType;
00054 
00055 It is also essential that you establish a model of ownership for each
00056 argument passed in an event record, i.e. whether particular arguments
00057 will be deleted by the event destruction callback, or whether they
00058 only loaned to the event handler callback, and guaranteed to persist
00059 until the time at which the handler is called.
00060 
00061 Sending Events
00062 --------------
00063 
00064 Events are initialized by PL_InitEvent and can be sent via
00065 PL_PostEvent or PL_PostSynchronousEvent. Events can also have an
00066 owner. The owner of an event can revoke all the events in a given
00067 event-queue by calling PL_RevokeEvents. An owner might want
00068 to do this if, for instance, it is being destroyed, and handling the
00069 events after the owner's destruction would cause an error (e.g. an
00070 MWContext).
00071 
00072 Since the act of initializing and posting an event must be coordinated
00073 with it's possible revocation, it is essential that the event-queue's
00074 monitor be entered surrounding the code that constructs, initializes
00075 and posts the event:
00076 
00077     void postMyEvent(MyOwner* owner, int x, char* y)
00078     {
00079               MyEventType* event;
00080 
00081               PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
00082 
00083               // construct
00084               event = PR_NEW(MyEventType);
00085               if (event == NULL) goto done;
00086 
00087               // initialize
00088               PL_InitEvent(event, owner,
00089                                     (PLHandleEventProc)handleMyEvent,
00090                                     (PLDestroyEventProc)destroyMyEvent);
00091               event->x = x;
00092               event->y = strdup(y);
00093 
00094               // post
00095               PL_PostEvent(myQueue, &event->e);
00096 
00097       done:
00098               PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
00099     }
00100 
00101 If you don't call PL_InitEvent and PL_PostEvent within the
00102 event-queue's monitor, you'll get a big red assert. 
00103 
00104 Handling Events
00105 ---------------
00106 
00107 To handle an event you must write a callback that is passed the event
00108 record you defined containing the event's arguments:
00109 
00110     void* handleMyEvent(MyEventType* event)
00111     {
00112               doit(event->x, event->y);
00113               return NULL;  // you could return a value for a sync event
00114     }
00115 
00116 Similarly for the destruction callback:
00117 
00118     void destroyMyEvent(MyEventType* event)
00119     {
00120               free(event->y);      // created by strdup
00121               free(event);
00122     }
00123 
00124 Processing Events in Your Event Loop
00125 ------------------------------------
00126 
00127 If your main loop only processes events delivered to the event queue,
00128 things are rather simple. You just get the next event (which may
00129 block), and then handle it:
00130 
00131     while (1) {
00132               event = PL_GetEvent(myQueue);
00133               PL_HandleEvent(event);
00134     }
00135 
00136 However, if other things must be waited on, you'll need to obtain a
00137 file-descriptor that represents your event queue, and hand it to select:
00138 
00139     fd = PL_GetEventQueueSelectFD(myQueue);
00140     ...add fd to select set...
00141     while (select(...)) {
00142               if (...fd...) {
00143                   PL_ProcessPendingEvents(myQueue);
00144               }
00145               ...
00146     }
00147 
00148 Of course, with Motif and Windows it's more complicated than that, and
00149 on Mac it's completely different, but you get the picture.
00150 
00151 Revoking Events
00152 ---------------
00153 If at any time an owner of events is about to be destroyed, you must
00154 take steps to ensure that no one tries to use the event queue after
00155 the owner is gone (or a crash may result). You can do this by either
00156 processing all the events in the queue before destroying the owner:
00157 
00158     {
00159               ...
00160               PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
00161               PL_ProcessPendingEvents(myQueue);
00162               DestroyMyOwner(owner);
00163               PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
00164               ...
00165     }
00166 
00167 or by revoking the events that are in the queue for that owner. This
00168 removes them from the queue and calls their destruction callback:
00169 
00170     {
00171               ...
00172               PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
00173               PL_RevokeEvents(myQueue, owner);
00174               DestroyMyOwner(owner);
00175               PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
00176               ...
00177     }
00178 
00179 In either case it is essential that you be in the event-queue's monitor
00180 to ensure that all events are removed from the queue for that owner, 
00181 and to ensure that no more events will be delivered for that owner.
00182 **********************************************************************/
00183 
00184 #ifndef plevent_h___
00185 #define plevent_h___
00186 
00187 #include "prtypes.h"
00188 #include "prclist.h"
00189 #include "prthread.h"
00190 #include "prlock.h"
00191 #include "prcvar.h"
00192 #include "prmon.h"
00193 
00194 #include "nscore.h"
00195 
00196 /* For HWND */
00197 #if defined(XP_WIN32)
00198 #include <windef.h>
00199 #elif defined(XP_OS2)
00200 #define INCL_DOSMISC
00201 #define INCL_DOSPROCESS
00202 #define INCL_DOSERRORS
00203 #define INCL_WINSHELLDATA
00204 #include <os2.h>
00205 #endif
00206 
00207 PR_BEGIN_EXTERN_C
00208 
00209 /* Typedefs */
00210 
00211 typedef struct PLEvent PLEvent;
00212 typedef struct PLEventQueue PLEventQueue;
00213 
00214 /*******************************************************************************
00215  * Event Queue Operations
00216  ******************************************************************************/
00217 
00218 /*
00219 ** Creates a new event queue. Returns NULL on failure.
00220 */
00221 NS_COM PLEventQueue*
00222 PL_CreateEventQueue(const char* name, PRThread* handlerThread);
00223 
00224 
00225 /* -----------------------------------------------------------------------
00226 ** FUNCTION: PL_CreateNativeEventQueue()
00227 ** 
00228 ** DESCRIPTION:
00229 ** PL_CreateNativeEventQueue() creates an event queue that
00230 ** uses platform specific notify mechanisms.
00231 ** 
00232 ** For Unix, the platform specific notify mechanism provides
00233 ** an FD that may be extracted using the function
00234 ** PL_GetEventQueueSelectFD(). The FD returned may be used in
00235 ** a select() function call.
00236 ** 
00237 ** For Windows, the platform specific notify mechanism
00238 ** provides an event receiver window that is called by
00239 ** Windows to process the event using the windows message
00240 ** pump engine.
00241 ** 
00242 ** INPUTS: 
00243 **  name:   A name, as a diagnostic aid.
00244 ** 
00245 **  handlerThread: A pointer to the PRThread structure for
00246 ** the thread that will "handle" events posted to this event
00247 ** queue.
00248 **
00249 ** RETURNS: 
00250 ** A pointer to a PLEventQueue structure or NULL.
00251 ** 
00252 */
00253 NS_COM PLEventQueue * 
00254     PL_CreateNativeEventQueue(
00255         const char *name, 
00256         PRThread *handlerThread
00257     );
00258 
00259 /* -----------------------------------------------------------------------
00260 ** FUNCTION: PL_CreateMonitoredEventQueue()
00261 ** 
00262 ** DESCRIPTION:
00263 ** PL_CreateMonitoredEventQueue() creates an event queue. No
00264 ** platform specific notify mechanism is created with the
00265 ** event queue.
00266 ** 
00267 ** Users of this type of event queue must explicitly poll the
00268 ** event queue to retreive and process events.
00269 ** 
00270 ** 
00271 ** INPUTS: 
00272 **  name:   A name, as a diagnostic aid.
00273 ** 
00274 **  handlerThread: A pointer to the PRThread structure for
00275 ** the thread that will "handle" events posted to this event
00276 ** queue.
00277 **
00278 ** RETURNS: 
00279 ** A pointer to a PLEventQueue structure or NULL.
00280 ** 
00281 */
00282 NS_COM PLEventQueue * 
00283     PL_CreateMonitoredEventQueue(
00284         const char *name,
00285         PRThread *handlerThread
00286     );
00287 
00288 /*
00289 ** Destroys an event queue.
00290 */
00291 NS_COM void
00292 PL_DestroyEventQueue(PLEventQueue* self);
00293 
00294 /* 
00295 ** Returns the monitor associated with an event queue. This monitor is 
00296 ** selectable. The monitor should be entered to protect against anyone 
00297 ** calling PL_RevokeEvents while the event is trying to be constructed
00298 ** and delivered.
00299 */
00300 NS_COM PRMonitor*
00301 PL_GetEventQueueMonitor(PLEventQueue* self);
00302 
00303 #define PL_ENTER_EVENT_QUEUE_MONITOR(queue)      \
00304        PR_EnterMonitor(PL_GetEventQueueMonitor(queue))
00305 
00306 #define PL_EXIT_EVENT_QUEUE_MONITOR(queue)       \
00307        PR_ExitMonitor(PL_GetEventQueueMonitor(queue))
00308 
00309 /*
00310 ** Posts an event to an event queue, waking up any threads waiting for an
00311 ** event. If event is NULL, notification still occurs, but no event will
00312 ** be available. 
00313 **
00314 ** Any events delivered by this routine will be destroyed by PL_HandleEvent
00315 ** when it is called (by the event-handling thread).
00316 */
00317 NS_COM PRStatus
00318 PL_PostEvent(PLEventQueue* self, PLEvent* event);
00319 
00320 /*
00321 ** Like PL_PostEvent, this routine posts an event to the event handling
00322 ** thread, but does so synchronously, waiting for the result. The result
00323 ** which is the value of the handler routine is returned.
00324 **
00325 ** Any events delivered by this routine will be not be destroyed by 
00326 ** PL_HandleEvent, but instead will be destroyed just before the result is
00327 ** returned (by the current thread).
00328 */
00329 NS_COM void*
00330 PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event);
00331 
00332 /*
00333 ** Gets an event from an event queue. Returns NULL if no event is
00334 ** available.
00335 */
00336 NS_COM PLEvent*
00337 PL_GetEvent(PLEventQueue* self);
00338 
00339 /*
00340 ** Returns true if there is an event available for PL_GetEvent.
00341 */
00342 NS_COM PRBool
00343 PL_EventAvailable(PLEventQueue* self);
00344 
00345 /*
00346 ** This is the type of the function that must be passed to PL_MapEvents
00347 ** (see description below).
00348 */
00349 typedef void 
00350 (PR_CALLBACK *PLEventFunProc)(PLEvent* event, void* data, PLEventQueue* queue);
00351 
00352 /*
00353 ** Applies a function to every event in the event queue. This can be used
00354 ** to selectively handle, filter, or remove events. The data pointer is
00355 ** passed to each invocation of the function fun.
00356 */
00357 NS_COM void
00358 PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data);
00359 
00360 /*
00361 ** This routine walks an event queue and destroys any event whose owner is
00362 ** the owner specified. The == operation is used to compare owners.
00363 */
00364 NS_COM void
00365 PL_RevokeEvents(PLEventQueue* self, void* owner);
00366 
00367 /*
00368 ** This routine processes all pending events in the event queue. It can be
00369 ** called from the thread's main event-processing loop whenever the event
00370 ** queue's selectFD is ready (returned by PL_GetEventQueueSelectFD).
00371 */
00372 NS_COM void
00373 PL_ProcessPendingEvents(PLEventQueue* self);
00374 
00375 /*******************************************************************************
00376  * Pure Event Queues
00377  *
00378  * For when you're only processing PLEvents and there is no native
00379  * select, thread messages, or AppleEvents.
00380  ******************************************************************************/
00381 
00382 /*
00383 ** Blocks until an event can be returned from the event queue. This routine
00384 ** may return NULL if the current thread is interrupted.
00385 */
00386 NS_COM PLEvent*
00387 PL_WaitForEvent(PLEventQueue* self);
00388 
00389 /*
00390 ** One stop shopping if all you're going to do is process PLEvents. Just
00391 ** call this and it loops forever processing events as they arrive. It will
00392 ** terminate when your thread is interrupted or dies.
00393 */
00394 NS_COM void
00395 PL_EventLoop(PLEventQueue* self);
00396 
00397 /*******************************************************************************
00398  * Native Event Queues
00399  *
00400  * For when you need to call select, or WaitNextEvent, and yet also want
00401  * to handle PLEvents.
00402  ******************************************************************************/
00403 
00404 /*
00405 ** This routine allows you to grab the file descriptor associated with an
00406 ** event queue and use it in the readFD set of select. Useful for platforms
00407 ** that support select, and must wait on other things besides just PLEvents.
00408 */
00409 NS_COM PRInt32
00410 PL_GetEventQueueSelectFD(PLEventQueue* self);
00411 
00412 /*
00413 **  This routine will allow you to check to see if the given eventQueue in
00414 **  on the current thread.  It will return PR_TRUE if so, else it will return
00415 **  PR_FALSE
00416 */
00417 NS_COM PRBool
00418     PL_IsQueueOnCurrentThread( PLEventQueue *queue );
00419 
00420 /*
00421 ** Returns whether the queue is native (true) or monitored (false)
00422 */
00423 NS_COM PRBool
00424 PL_IsQueueNative(PLEventQueue *queue);
00425 
00426 /*******************************************************************************
00427  * Event Operations
00428  ******************************************************************************/
00429 
00430 /*
00431 ** The type of an event handler function. This function is passed as an
00432 ** initialization argument to PL_InitEvent, and called by
00433 ** PL_HandleEvent. If the event is called synchronously, a void* result 
00434 ** may be returned (otherwise any result will be ignored).
00435 */
00436 typedef void*
00437 (PR_CALLBACK *PLHandleEventProc)(PLEvent* self);
00438 
00439 /*
00440 ** The type of an event destructor function. This function is passed as
00441 ** an initialization argument to PL_InitEvent, and called by
00442 ** PL_DestroyEvent.
00443 */
00444 typedef void
00445 (PR_CALLBACK *PLDestroyEventProc)(PLEvent* self);
00446 
00447 /*
00448 ** Initializes an event. Usually events are embedded in a larger event
00449 ** structure which holds event-specific data, so this is an initializer
00450 ** for that embedded part of the structure.
00451 */
00452 NS_COM void
00453 PL_InitEvent(PLEvent* self, void* owner,
00454                       PLHandleEventProc handler,
00455                       PLDestroyEventProc destructor);
00456 
00457 /*
00458 ** Returns the owner of an event. 
00459 */
00460 NS_COM void*
00461 PL_GetEventOwner(PLEvent* self);
00462 
00463 /*
00464 ** Handles an event, calling the event's handler routine.
00465 */
00466 NS_COM void
00467 PL_HandleEvent(PLEvent* self);
00468 
00469 /*
00470 ** Destroys an event, calling the event's destructor.
00471 */
00472 NS_COM void
00473 PL_DestroyEvent(PLEvent* self);
00474 
00475 /*
00476 ** Removes an event from an event queue.
00477 */
00478 NS_COM void
00479 PL_DequeueEvent(PLEvent* self, PLEventQueue* queue);
00480 
00481 
00482 /*
00483  * Give hint to native PL_Event notification mechanism. If the native 
00484  * platform needs to tradeoff performance vs. native event starvation
00485  * this hint tells the native dispatch code which to favor.
00486  * The default is to prevent event starvation. 
00487  * 
00488  * Calls to this function may be nested. When the number of calls that 
00489  * pass PR_TRUE is subtracted from the number of calls that pass PR_FALSE 
00490  * is greater than 0, performance is given precedence over preventing 
00491  * event starvation.
00492  *
00493  * The starvationDelay arg is only used when 
00494  * favorPerformanceOverEventStarvation is PR_FALSE. It is the
00495  * amount of time in milliseconds to wait before the PR_FALSE actually 
00496  * takes effect.
00497  */
00498 NS_COM void
00499 PL_FavorPerformanceHint(PRBool favorPerformanceOverEventStarvation, PRUint32 starvationDelay);
00500 
00501 
00502 /*******************************************************************************
00503  * Private Stuff
00504  ******************************************************************************/
00505 
00506 struct PLEvent {
00507     PRCList                        link;
00508     PLHandleEventProc       handler;
00509     PLDestroyEventProc      destructor;
00510     void*                          owner;
00511     void*                          synchronousResult;
00512     PRLock*             lock;
00513     PRCondVar*          condVar;
00514     PRBool              handled;
00515 #ifdef PL_POST_TIMINGS
00516     PRIntervalTime      postTime;
00517 #endif
00518 #ifdef XP_UNIX
00519     unsigned long       id;
00520 #endif /* XP_UNIX */
00521     /* other fields follow... */
00522 };
00523 
00524 /******************************************************************************/
00525 
00526 /*
00527 ** Returns the event queue associated with the main thread.
00528 ** 
00529 */
00530 #if defined(XP_WIN) || defined(XP_OS2)
00531 /* -----------------------------------------------------------------------
00532 ** FUNCTION: PL_GetNativeEventReceiverWindow()
00533 ** 
00534 ** DESCRIPTION:
00535 ** PL_GetNativeEventReceiverWindow() returns the windows
00536 ** handle of the event receiver window associated with the
00537 ** referenced PLEventQueue argument.
00538 ** 
00539 ** INPUTS: 
00540 **  PLEventQueue pointer
00541 **
00542 ** RETURNS:
00543 **  event receiver window handle.
00544 ** 
00545 ** RESTRICTIONS: MS-Windows ONLY.
00546 ** 
00547 */
00548 NS_COM HWND 
00549     PL_GetNativeEventReceiverWindow( 
00550         PLEventQueue *eqp 
00551     );
00552 #endif /* XP_WIN || XP_OS2 */
00553 
00554 #ifdef XP_UNIX
00555 /* -----------------------------------------------------------------------
00556 ** FUNCTION: PL_ProcessEventsBeforeID()
00557 **
00558 ** DESCRIPTION:
00559 **
00560 ** PL_ProcessEventsBeforeID() will process events in a native event
00561 ** queue that have an id that is older than the ID passed in.
00562 **
00563 ** INPUTS:
00564 **  PLEventQueue *aSelf
00565 **  unsigned long aID
00566 **
00567 ** RETURNS:
00568 **  PRInt32 number of requests processed, -1 on error.
00569 **
00570 ** RESTRICTIONS: Unix only (well, X based unix only)
00571 */
00572 NS_COM PRInt32
00573 PL_ProcessEventsBeforeID(PLEventQueue *aSelf, unsigned long aID);
00574 
00575 /* This prototype is a function that can be called when an event is
00576    posted to stick an ID on it.  */
00577 
00578 typedef unsigned long
00579 (PR_CALLBACK *PLGetEventIDFunc)(void *aClosure);
00580 
00581 
00582 /* -----------------------------------------------------------------------
00583 ** FUNCTION: PL_RegisterEventIDFunc()
00584 **
00585 ** DESCRIPTION:
00586 **
00587 ** This function registers a function for getting the ID on unix for
00588 ** this event queue.
00589 **
00590 ** INPUTS:
00591 **  PLEventQueue *aSelf
00592 **  PLGetEventIDFunc func
00593 **  void *aClosure
00594 **
00595 ** RETURNS:
00596 **  void
00597 **
00598 ** RESTRICTIONS: Unix only (well, X based unix only) */
00599 NS_COM void
00600 PL_RegisterEventIDFunc(PLEventQueue *aSelf, PLGetEventIDFunc aFunc,
00601                        void *aClosure);
00602 
00603 /* -----------------------------------------------------------------------
00604 ** FUNCTION: PL_RegisterEventIDFunc()
00605 **
00606 ** DESCRIPTION:
00607 **
00608 ** This function unregisters a function for getting the ID on unix for
00609 ** this event queue.
00610 **
00611 ** INPUTS:
00612 **  PLEventQueue *aSelf
00613 **
00614 ** RETURNS:
00615 **  void
00616 **
00617 ** RESTRICTIONS: Unix only (well, X based unix only) */
00618 NS_COM void
00619 PL_UnregisterEventIDFunc(PLEventQueue *aSelf);
00620 
00621 #endif /* XP_UNIX */
00622 
00623 
00624 /* ----------------------------------------------------------------------- */
00625 
00626 #if defined(NO_NSPR_10_SUPPORT)
00627 #else
00628 /********* ???????????????? FIX ME       ??????????????????????????? *****/
00629 /********************** Some old definitions *****************************/
00630 
00631 /* Re: prevent.h->plevent.h */
00632 #define PREvent PLEvent
00633 #define PREventQueue PLEventQueue
00634 #define PR_CreateEventQueue PL_CreateEventQueue
00635 #define PR_DestroyEventQueue PL_DestroyEventQueue
00636 #define PR_GetEventQueueMonitor PL_GetEventQueueMonitor
00637 #define PR_ENTER_EVENT_QUEUE_MONITOR PL_ENTER_EVENT_QUEUE_MONITOR
00638 #define PR_EXIT_EVENT_QUEUE_MONITOR PL_EXIT_EVENT_QUEUE_MONITOR
00639 #define PR_PostEvent PL_PostEvent
00640 #define PR_PostSynchronousEvent PL_PostSynchronousEvent
00641 #define PR_GetEvent PL_GetEvent
00642 #define PR_EventAvailable PL_EventAvailable
00643 #define PREventFunProc PLEventFunProc
00644 #define PR_MapEvents PL_MapEvents
00645 #define PR_RevokeEvents PL_RevokeEvents
00646 #define PR_ProcessPendingEvents PL_ProcessPendingEvents
00647 #define PR_WaitForEvent PL_WaitForEvent
00648 #define PR_EventLoop PL_EventLoop
00649 #define PR_GetEventQueueSelectFD PL_GetEventQueueSelectFD
00650 #define PRHandleEventProc PLHandleEventProc
00651 #define PRDestroyEventProc PLDestroyEventProc
00652 #define PR_InitEvent PL_InitEvent
00653 #define PR_GetEventOwner PL_GetEventOwner
00654 #define PR_HandleEvent PL_HandleEvent
00655 #define PR_DestroyEvent PL_DestroyEvent
00656 #define PR_DequeueEvent PL_DequeueEvent
00657 #define PR_GetMainEventQueue PL_GetMainEventQueue
00658 
00659 /********* ????????????? End Fix me ?????????????????????????????? *****/
00660 #endif /* NO_NSPR_10_SUPPORT */
00661 
00662 PR_END_EXTERN_C
00663 
00664 #endif /* plevent_h___ */