home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / lib / ds / plevent.h < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  12.1 KB  |  404 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /**********************************************************************
  20. NSPL Events
  21.  
  22. Defining Events
  23. ---------------
  24.  
  25. Events are essentially structures that represent argument lists for a
  26. function that will run on another thread. All event structures you
  27. define must include a PLEvent struct as their first field:
  28.  
  29.     typedef struct MyEventType {
  30.         PLEvent    e;
  31.         // arguments follow...
  32.         int    x;
  33.         char*    y;
  34.     } MyEventType;
  35.  
  36. It is also essential that you establish a model of ownership for each
  37. argument passed in an event record, i.e. whether particular arguments
  38. will be deleted by the event destruction callback, or whether they
  39. only loaned to the event handler callback, and guaranteed to persist
  40. until the time at which the handler is called.
  41.  
  42. Sending Events
  43. --------------
  44.  
  45. Events are initialized by PL_InitEvent and can be sent via
  46. PL_PostEvent or PL_PostSynchronousEvent. Events can also have an
  47. owner. The owner of an event can revoke all the events in a given
  48. event-queue by calling PL_RevokeEvents. An owner might want
  49. to do this if, for instance, it is being destroyed, and handling the
  50. events after the owner's destruction would cause an error (e.g. an
  51. MWContext).
  52.  
  53. Since the act of initializing and posting an event must be coordinated
  54. with it's possible revocation, it is essential that the event-queue's
  55. monitor be entered surrounding the code that constructs, initializes
  56. and posts the event:
  57.  
  58.     void postMyEvent(MyOwner* owner, int x, char* y)
  59.     {
  60.         MyEventType* event;
  61.  
  62.         PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
  63.  
  64.         // construct
  65.         event = PR_NEW(MyEventType);
  66.         if (event == NULL) goto done;
  67.  
  68.         // initialize
  69.         PL_InitEvent(event, owner,
  70.                      (PLHandleEventProc)handleMyEvent,
  71.                      (PLDestroyEventProc)destroyMyEvent);
  72.         event->x = x;
  73.         event->y = strdup(y);
  74.  
  75.         // post
  76.         PL_PostEvent(myQueue, &event->e);
  77.  
  78.       done:
  79.         PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
  80.     }
  81.  
  82. If you don't call PL_InitEvent and PL_PostEvent within the
  83. event-queue's monitor, you'll get a big red assert. 
  84.  
  85. Handling Events
  86. ---------------
  87.  
  88. To handle an event you must write a callback that is passed the event
  89. record you defined containing the event's arguments:
  90.  
  91.     void* handleMyEvent(MyEventType* event)
  92.     {
  93.         doit(event->x, event->y);
  94.         return NULL;    // you could return a value for a sync event
  95.     }
  96.  
  97. Similarly for the destruction callback:
  98.  
  99.     void destroyMyEvent(MyEventType* event)
  100.     {
  101.         free(event->y);    // created by strdup
  102.         free(event);
  103.     }
  104.  
  105. Processing Events in Your Event Loop
  106. ------------------------------------
  107.  
  108. If your main loop only processes events delivered to the event queue,
  109. things are rather simple. You just get the next event (which may
  110. block), and then handle it:
  111.  
  112.     while (1) {
  113.         event = PL_GetEvent(myQueue);
  114.         PL_HandleEvent(event);
  115.     }
  116.  
  117. However, if other things must be waited on, you'll need to obtain a
  118. file-descriptor that represents your event queue, and hand it to select:
  119.  
  120.     fd = PL_GetEventQueueSelectFD(myQueue);
  121.     ...add fd to select set...
  122.     while (select(...)) {
  123.         if (...fd...) {
  124.             PL_ProcessPendingEvents(myQueue);
  125.         }
  126.         ...
  127.     }
  128.  
  129. Of course, with Motif and Windows it's more complicated than that, and
  130. on Mac it's completely different, but you get the picture.
  131.  
  132. Revoking Events
  133. ---------------
  134. If at any time an owner of events is about to be destroyed, you must
  135. take steps to ensure that no one tries to use the event queue after
  136. the owner is gone (or a crash may result). You can do this by either
  137. processing all the events in the queue before destroying the owner:
  138.  
  139.     {
  140.         ...
  141.         PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
  142.         PL_ProcessPendingEvents(myQueue);
  143.         DestroyMyOwner(owner);
  144.         PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
  145.         ...
  146.     }
  147.  
  148. or by revoking the events that are in the queue for that owner. This
  149. removes them from the queue and calls their destruction callback:
  150.  
  151.     {
  152.         ...
  153.         PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
  154.         PL_RevokeEvents(myQueue, owner);
  155.         DestroyMyOwner(owner);
  156.         PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
  157.         ...
  158.     }
  159.  
  160. In either case it is essential that you be in the event-queue's monitor
  161. to ensure that all events are removed from the queue for that owner, 
  162. and to ensure that no more events will be delivered for that owner.
  163. **********************************************************************/
  164.  
  165. #ifndef prevent_h___
  166. #define prevent_h___
  167.  
  168. #include "prtypes.h"
  169. #include "prclist.h"
  170. #include "prthread.h"
  171. #include "prmon.h"
  172.  
  173. PR_BEGIN_EXTERN_C
  174.  
  175. /* Typedefs */
  176.  
  177. typedef struct PLEvent PLEvent;
  178. typedef struct PLEventQueue PLEventQueue;
  179.  
  180. /*******************************************************************************
  181.  * Event Queue Operations
  182.  ******************************************************************************/
  183.  
  184. /*
  185. ** Creates a new event queue. Returns NULL on failure.
  186. */
  187. PR_EXTERN(PLEventQueue*)
  188. PL_CreateEventQueue(char* name, PRThread* handlerThread);
  189.  
  190. /*
  191. ** Destroys an event queue.
  192. */
  193. PR_EXTERN(void)
  194. PL_DestroyEventQueue(PLEventQueue* self);
  195.  
  196. /* 
  197. ** Returns the monitor associated with an event queue. This monitor is 
  198. ** selectable. The monitor should be entered to protect against anyone 
  199. ** calling PL_RevokeEvents while the event is trying to be constructed
  200. ** and delivered.
  201. */
  202. PR_EXTERN(PRMonitor*)
  203. PL_GetEventQueueMonitor(PLEventQueue* self);
  204.  
  205. #define PL_ENTER_EVENT_QUEUE_MONITOR(queue)    \
  206.     PR_EnterMonitor(PL_GetEventQueueMonitor(queue))
  207.  
  208. #define PL_EXIT_EVENT_QUEUE_MONITOR(queue)    \
  209.     PR_ExitMonitor(PL_GetEventQueueMonitor(queue))
  210.  
  211. /*
  212. ** Posts an event to an event queue, waking up any threads waiting for an
  213. ** event. If event is NULL, notification still occurs, but no event will
  214. ** be available. 
  215. **
  216. ** Any events delivered by this routine will be destroyed by PL_HandleEvent
  217. ** when it is called (by the event-handling thread).
  218. */
  219. PR_EXTERN(PRStatus)
  220. PL_PostEvent(PLEventQueue* self, PLEvent* event);
  221.  
  222. /*
  223. ** Like PL_PostEvent, this routine posts an event to the event handling
  224. ** thread, but does so synchronously, waiting for the result. The result
  225. ** which is the value of the handler routine is returned.
  226. **
  227. ** Any events delivered by this routine will be not be destroyed by 
  228. ** PL_HandleEvent, but instead will be destroyed just before the result is
  229. ** returned (by the current thread).
  230. */
  231. PR_EXTERN(void*)
  232. PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event);
  233.  
  234. /*
  235. ** Gets an event from an event queue. Returns NULL if no event is
  236. ** available.
  237. */
  238. PR_EXTERN(PLEvent*)
  239. PL_GetEvent(PLEventQueue* self);
  240.  
  241. /*
  242. ** Returns true if there is an event available for PL_GetEvent.
  243. */
  244. PR_EXTERN(PRBool)
  245. PL_EventAvailable(PLEventQueue* self);
  246.  
  247. /*
  248. ** This is the type of the function that must be passed to PL_MapEvents
  249. ** (see description below).
  250. */
  251. typedef void 
  252. (PR_CALLBACK *PLEventFunProc)(PLEvent* event, void* data, PLEventQueue* queue);
  253.  
  254. /*
  255. ** Applies a function to every event in the event queue. This can be used
  256. ** to selectively handle, filter, or remove events. The data pointer is
  257. ** passed to each invocation of the function fun.
  258. */
  259. PR_EXTERN(void)
  260. PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data);
  261.  
  262. /*
  263. ** This routine walks an event queue and destroys any event whose owner is
  264. ** the owner specified. The == operation is used to compare owners.
  265. */
  266. PR_EXTERN(void)
  267. PL_RevokeEvents(PLEventQueue* self, void* owner);
  268.  
  269. /*
  270. ** This routine processes all pending events in the event queue. It can be
  271. ** called from the thread's main event-processing loop whenever the event
  272. ** queue's selectFD is ready (returned by PL_GetEventQueueSelectFD).
  273. */
  274. PR_EXTERN(void)
  275. PL_ProcessPendingEvents(PLEventQueue* self);
  276.  
  277. /*******************************************************************************
  278.  * Pure Event Queues
  279.  *
  280.  * For when you're only processing PLEvents and there is no native
  281.  * select, thread messages, or AppleEvents.
  282.  ******************************************************************************/
  283.  
  284. /*
  285. ** Blocks until an event can be returned from the event queue. This routine
  286. ** may return NULL if the current thread is interrupted.
  287. */
  288. PR_EXTERN(PLEvent*)
  289. PL_WaitForEvent(PLEventQueue* self);
  290.  
  291. /*
  292. ** One stop shopping if all you're going to do is process PLEvents. Just
  293. ** call this and it loops forever processing events as they arrive. It will
  294. ** terminate when your thread is interrupted or dies.
  295. */
  296. PR_EXTERN(void)
  297. PL_EventLoop(PLEventQueue* self);
  298.  
  299. /*******************************************************************************
  300.  * Native Event Queues
  301.  *
  302.  * For when you need to call select, or WaitNextEvent, and yet also want
  303.  * to handle PLEvents.
  304.  ******************************************************************************/
  305.  
  306. /*
  307. ** This routine allows you to grab the file descriptor associated with an
  308. ** event queue and use it in the readFD set of select. Useful for platforms
  309. ** that support select, and must wait on other things besides just PLEvents.
  310. */
  311. PR_EXTERN(PRInt32)
  312. PL_GetEventQueueSelectFD(PLEventQueue* self);
  313.  
  314. /*******************************************************************************
  315.  * Event Operations
  316.  ******************************************************************************/
  317.  
  318. /*
  319. ** The type of an event handler function. This function is passed as an
  320. ** initialization argument to PL_InitEvent, and called by
  321. ** PL_HandleEvent. If the event is called synchronously, a void* result 
  322. ** may be returned (otherwise any result will be ignored).
  323. */
  324. typedef void*
  325. (PR_CALLBACK *PLHandleEventProc)(PLEvent* self);
  326.  
  327. /*
  328. ** The type of an event destructor function. This function is passed as
  329. ** an initialization argument to PL_InitEvent, and called by
  330. ** PL_DestroyEvent.
  331. */
  332. typedef void
  333. (PR_CALLBACK *PLDestroyEventProc)(PLEvent* self);
  334.  
  335. /*
  336. ** Initializes an event. Usually events are embedded in a larger event
  337. ** structure which holds event-specific data, so this is an initializer
  338. ** for that embedded part of the structure.
  339. */
  340. PR_EXTERN(void)
  341. PL_InitEvent(PLEvent* self, void* owner,
  342.              PLHandleEventProc handler,
  343.              PLDestroyEventProc destructor);
  344.  
  345. /*
  346. ** Returns the owner of an event. 
  347. */
  348. PR_EXTERN(void*)
  349. PL_GetEventOwner(PLEvent* self);
  350.  
  351. /*
  352. ** Handles an event, calling the event's handler routine.
  353. */
  354. PR_EXTERN(void)
  355. PL_HandleEvent(PLEvent* self);
  356.  
  357. /*
  358. ** Destroys an event, calling the event's destructor.
  359. */
  360. PR_EXTERN(void)
  361. PL_DestroyEvent(PLEvent* self);
  362.  
  363. /*
  364. ** Removes an event from an event queue.
  365. */
  366. PR_EXTERN(void)
  367. PL_DequeueEvent(PLEvent* self, PLEventQueue* queue);
  368.  
  369. #if defined(_WIN32) || defined(WIN16)
  370. PR_EXTERN(HWND)
  371. PR_GetEventReceiverWindow();
  372. #endif
  373.  
  374.  
  375. /*******************************************************************************
  376.  * Private Stuff
  377.  ******************************************************************************/
  378.  
  379. struct PLEvent {
  380.     PRCList                link;
  381.     PLHandleEventProc    handler;
  382.     PLDestroyEventProc    destructor;
  383.     void*                owner;
  384.     void*                synchronousResult;
  385.     /* other fields follow... */
  386. };
  387.  
  388. /******************************************************************************/
  389.  
  390. /*
  391. ** Returns the event queue associated with the main thread. Note that
  392. ** the event queue is now created by NSPR.
  393. */
  394. #ifdef XP_PC
  395. PR_EXTERN(PLEventQueue *)
  396. PL_GetMainEventQueue(void);
  397. PR_EXTERN(void)
  398. PL_InitializeEventsLib(char *name);
  399. #endif /* XP_PC */
  400.  
  401. PR_END_EXTERN_C
  402.  
  403. #endif /* prevent_h___ */
  404.