Newsgroups: comp.windows.x Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!van-bc!ubc-cs!mprgate.mpr.ca!mprgate.mpr.ca!janzen From: janzen@mprgate.mpr.ca (Martin Janzen) Subject: Re: Event Loops Message-ID: <1991Apr18.000420.7600@mprgate.mpr.ca> Sender: news@mprgate.mpr.ca Reply-To: janzen@mprgate.mpr.ca (Martin Janzen) Organization: MPR Teltech Ltd. References: <24267@well.sf.ca.us> Distribution: na Date: Thu, 18 Apr 91 00:04:20 GMT In article <24267@well.sf.ca.us>, bschoen@well.sf.ca.us (Brook Schoenfield) writes: >malbert@jeeves.shearson.com (Marc Albert) writes: >>I have an application that has multiple top level windows. The event >>loop looks something like this: > >> for (;;) { >> if (XtAppPending(WindowOne)) >> XtDispatch(); > >> if (XtAppPending(WindowTwo)) >> XtDispatch(); >> } >> >>This method works fine. The only problem I have is that >>I have to poll for events; this means I am never really >>waiting (blocking) and I am burning a lot of CPU. > >XtAppPending() returns whether or not an event is avaliable: >why not use XtAppNextEvent(), which blocks until an event is >available? (I've just been digging through NextEvent.c, trying to get X apps to work as RPC clients and servers -- so I'll throw in my $0.02 worth.) Be careful with this. If your application contexts (call them app1 and app2) are connected to different displays, and you call XtAppNextEvent(app1, &event) when no events are pending on the display connection for app1, then your process will block until the next event is received on *that* connection. No events in app2 will be processed until an event occurs on the display connection for app1. This happens because XtAppNextEvent() does a select() on the file descriptors for all displays *in the specified application context*. Iff both of your application contexts share the same display connection (Is this possible? How would you set this up anyway?), then XtAppNextEvent() should work. O'Reilly (Vol. 4, 13.6) discusses multiple application contexts a little, but doesn't present a real solution to this problem, so get ready for some experimentation! You could try blocking by doing your own select() on the file descriptors for the display connections in each application context, something like this: #include #include int dtablesize; fd_set display_fds; int fd_width; fd_set read_mask; ... /* after you've opened displays d1 and d2 in each application context: */ fd_width = getdtablesize(); FD_ZERO(&display_fds); FD_SET(ConnectionNumber(d1), &display_fds); FD_SET(ConnectionNumber(d2), &display_fds); ... /* in your main loop, if no events are pending in either app context: */ read_mask = display_fds; select(fd_width, &read_mask, NULL, NULL, NULL); (Note that if you want to use XtAddTimeOut, XtAddInput, or XtAddWorkProc as well, then things become even more complicated -- see NextEvent.c for the gory details!) Alternatively, you could just try adding a short usleep() if no events are pending in either application context. Not pretty, but better than burning all your CPU cycles! >If you need to do processing while waiting for user events, you >can set up a timer event and callback to do the background processing. >[...] You didn't mention this in the original message, but anyone who needs to do background processing should check out XtAddWorkProc/XtRemoveWorkProc... >Happy Coding Ditto! -- Martin Janzen janzen@mprgate.mpr.ca (134.87.131.13) MPR Teltech Ltd. Phone: (604) 293-5309 8999 Nelson Way Fax: (604) 293-5787 Burnaby, BC, CANADA V5A 4B5