attempt to do direct dispatching from within a callback routine or any function that has been
called indirectly by the Notifier.
These two methods of dispatching make porting programs that do not use the Notifier much
easier. Thus, building an XView interface on top of a typical mainline-based, input-driven
program is also much easier. Programs written from scratch should try to follow the event-
driven input style of program design and try to avoid using implicit or explicit dispatching
whenever possible.
20.10.1 Mass Destruction
The following routine causes all the client destruction routines to be called immediately with
a destroy status set to status:
Notify_error
notify_die(status)
Destroy_status status;
This routine causes all the client destruction functions to be called immediately with sta-
tus as the reason. The return values are NOTIFY_OK or NOTIFY_DESTROY_VETOED; the lat-
ter indicates that someone called notify_veto_destroy() and status was DES-
TROY_CHECKING
. It is then the responsibility of the caller of notify_die() to exit the
process, if so desired. Refer to the discussion on notify_post_destroy for more infor-
mation.
20.10.2 Implicit Dispatching
Implicit dispatching is used whenever you wish to loop on a call that might block, such as
read (2). Before calling read(), you should first call the function: notify_do_dis-
patch(); This tells the Notifier that you are going to do implicit dispatching and that it
should use its own version of read() rather than using the standard system call as the func-
tion. The two are equivalent with one exception:read() will return 0 on EOF rather than
-1, as you might expect.
After notify_do_dispatch() has been called, you can call notify_dispatch()
directly (to process events you know have already been delivered), call read(), or both.
The following example program demonstrates how this can be done. The program creates
our usual frame, panel, and “Quit” panel button, but instead of calling xv_main_loop(),
we create a small loop which reads stdin waiting for typed input.
Notifier
The Notifier 499
Example 20-7. The ntfy_do_dis.c program
/*
* ntfy_do_dis.c -- show an example of implicit notifier dispatching
* by calling notify_do_dispatch(). Create a frame, panel and "Quit"
* button, and then loop on calls to read() from stdin. Event
* processing is still maintained because the Notifier uses its own
* non-blocking read().
*/
#include <stdio.h>
#include <xview/xview.h>
#include <xview/frame.h>
#include <xview/panel.h>
Frame frame;
main (argc, argv)
int argc;
char *argv[ ];
{
Panel panel;
char buf[BUFSIZ];
int n, quit();
xv_init (XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);
frame = (Frame)xv_create (NULL, FRAME,
FRAME_LABEL, argv[0 ],
XV_WIDTH, 200,
XV_HEIGHT, 100,
XV_SHOW, TRUE,
NULL);
panel = (Panel)xv_create (frame, PANEL, NULL);
(void) xv_create (panel, PANEL_BUTTON,
PANEL_LABEL_STRING, "Quit",
PANEL_NOTIFY_PROC, quit,
NULL);
/* Force the frame to be displayed by flushing the server */
XFlush(xv_get(frame, XV_DISPLAY));
/* tell the Notifier that it should use its own read() so that it
* can also detect and dispatch events. This allows us to loop
* in this code segment and still process events.
*/
notify_do_dispatch();
puts("Frame being displayed -- type away.");
while ((n = read(0, buf, sizeof buf)) >= 0)
printf("read %d bytes0, n);
printf("read() returned %d0, n);
}
int
quit()
500 XView Programming Manual
Example 20-7. The ntfy_do_dis.c program (continued)
{
xv_destroy_safe(frame);
return XV_OK;
}
There are several things to note here. First, because xv_main_loop() is not called, we
need to explicitly set the attribute XV_SHOW to TRUE for the base frame. Otherwise, it will
never be displayed. Also, because of the nature of event dispatching, we must flush the con-
nection between the X server and the application to make sure that the frame is displayed by
the time the first read() call returns. If this is not done, the frame is not displayed until
after the first read() returns.
20.10.3 Explicit Dispatching
Frequently, the programmer is plagued with the following problem: A great deal of process-
ing has to be done to process something that the user has initiated. As mentioned before, the
programmer might want to generate a fractal image or compute the value of pi when the user
selects a panel button. Any time-consuming process that requires this type of functionality
should utilize explicit dispatching. It seems like an easy solution to fork() and let the
background process perform the operation, but this is frequently an expensive operation and
should be avoided if explicit dispatching is sufficient. If forking is required, then refer to
Section 20.5.5, “Handling
SIGCHLD,” and Section 20.8.2, “Reading and Writing on Pipes.”
The call notify_dispatch() does explicit event dispatching immediately to service an
event that you know is waiting to be read and dispatched. Typically, this is called at particu-
lar locations within a control loop that is processing time consuming tasks. It is assumed that
this control loop does not call read() or select(). Rather, explicit dispatching is used
within loops that might do heavy computation such as graphics processing or number crunch-
ing. This is necessary because while the computations are busy computing, the user might be
attempting to interact with the application by selecting a panel button.
If notify_dispatch() is called frequently enough, then performance of the user inter-
face may still be perceived as acceptable even though the program is very busy with its com-
putations. Architecturally, such a program is designed in a similar way with ntfy_do_dis.c in
Section 20.10.1, “Implicit Dispatching.” That is, there is a central processing loop which is
doing the main work of the program. In this case, notify_do_dispatch() is not called.
#include <xview/xview.h>
...
int finished;
main(argc, argv)
char *argv[ ];
{
Display *dpy;
Frame frame;
...
xv_create(NULL, FRAME, NULL);
Notifier
The Notifier 501
...
dpy = (Display *)xv_get(frame, XV_DISPLAY);
/* flush everything before starting loop */
XFlush(dpy);
while (!finished) {
notify_dispatch();
XFlush(dpy);
/* compute PI to the next place */
process_pi();
}
}
Notice that after notify_dispatch(), XFlush() is called. It is imperative that this
happen; otherwise, any Xlib calls (which result from many xv_create() or xv_set()
calls) may not be displayed. You only need to call XFlush() once after one or more calls
to a sequence of calls to notify_dispatch(). The rule of thumb is to flush the server
whenever you want to see the latest display.
20.11 Emulating a sleep() Call
XView allows you to emulate the system call sleep(). You cannot simply make the call
since this would cause problems for the Notifier. Example 20-8 demonstrates how XView
applications can implement a “sleep.”
Example 20-8. Emulating a sleep
#include <xview/xview.h>
#include <xview/panel.h>
#include <sys/time.h>
Frame frame;
Panel panel;
main(argc,argv)
int argc;
char *argv[ ];
{
int sleep_for_awhile();
xv_init(XV_INIT_ARGS, argc,argv, 0);
frame = xv_create(0,FRAME, 0);
panel = xv_create(frame,PANEL, 0);
xv_create(panel,PANEL_BUTTON,
PANEL_NOTIFY_PROC, sleep_for_awhile,
PANEL_LABEL_IMAGE,
panel_button_image(panel,"Sleep For Awhile",0,0),
NULL);
window_fit(panel);
window_fit(frame);
502 XView Programming Manual
Example 20-8. Emulating a sleep (continued)
xv_main_loop(frame);
}
sleep_for_awhile()
{
sleep(5);
}
sleep(sec)
int sec;
{
our_sleep(sec,0);
}
usleep(usec)
int usec;
{
our_sleep(0,usec);
}
our_sleep(sec,usec)
int sec,usec;
{
int oldmask,mask;
struct timeval tv;
tv.tv_sec = sec;
tv.tv_usec = usec;
mask = sigmask(SIGIO);
mask |= sigmask(SIGALRM); /* change = to |= JLM */
oldmask = sigblock(mask);
if ((select(0,0,0,0,&tv)) == -1) {
perror("select");
}
sigsetmask(oldmask);
}
20.12 Advanced Notifier Usage
This section covers Notifier prioritization and scheduling. These topics should be considered
advanced topics, since their use changes the way XView schedules and prioritizes event
handling in the Notifier. If you incorrectly modify these areas of the Notifier, you may expe-
rience severe problems with your application.
Notifier
The Notifier 503

Get Volume 7A: XView Programming Manual now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.