Path: utzoo!attcan!uunet!wuarchive!gem.mps.ohio-state.edu!ginosko!gjc
From: gjc@eileen.mga.com (George J. Carrette)
Newsgroups: comp.windows.x
Subject: The problem of fitting your application into XtAppMainLoop.
Message-ID: <61@eileen.mga.com>
Date: 27 Sep 89 22:52:01 GMT
Organization: Mitchell and Gauthier Associates
Lines: 82

Design questions and requests for comments on XT application main loop
issues. I am particularly interested in hearing from X Designers about
the legality (e.g. long term usability and portability, reentrancy
considerations) of simple solution #2. 

At first glance it is very difficult if not impossible in some
applications to always return within a short time from procedures
invoked by the XtAppAddWorkProc mechanism in the XtAppMainLoop.  (And
indeed going to a WorkProc itself requires a callback to QUEUE some
work rather than to try to complete the work while inside the
callback).

Examples:
 (*) hit the RUN button on a simulator, for example an x-window interface to
     SPICE.
 (*) loading/saving or compiling a knowledge base in an expert system shell.
 (*) hit the RUN button in an expert system.
 (*) an X-window interface to Macsyma, which may compute something fast or
     very slowly.

There are four ways to deal with this:
(1) Write an interposer process. Communicate with a subprocess through
    a pipe (or vms mailbox) to do the actual work.
  Advantage: Solves the problem in a conceptually simple way.
  Disadvantages: 
   * You must use a remote-procedure-call-like mechanism. You must maintain
     both sides of an imposed protocol. You may have to spend a lot of time
     in the long run in designing this protocol and maintaining it.
   * Access to data structures such as the graphical representation of
     objects being edited, simulation statements, rules, etc, is either
     much more restricted and slow (through the pipe) or much more complex
     (through a shared-memory interlocked database) and non-portable.

(2) When you are in the XtAppAddWorkProc invoked procedure which is going to
    compute for a long time, arrange to POLL for x-events in various places
    in your code. 
  Advantage: For most simulators, expert systems, anything with a loop or
  with frequent calls to a few known routines, this is rather easy to set up.
  ??Disadvantage??: None that I can seen or experimentally determine now.

  Code fragments to give you an idea of the implementation:
  
XtCallbackProc cb_set_abort_flag(widget,tag,reason)
/* a call-back for a work-in-progress box cancel button */
{abort_on_next_poll = 1;}

void decw_events_poll()
{long want_mask;
 if (abort_on_next_poll)
   {abort_on_next_poll = 0;
    error_longjump("ABORTED",NIL);}
 want_mask = XtIMXEvent | XtIMTimer;
 if ((XtAppPending(context) & want_mask) != 0)
   XtAppProcessEvent(context,want_mask);
 if (abort_on_next_poll)
   {abort_on_next_poll = 0;
    error_logjump("ABORTED",NIL);}}

#define POLLING_HANDLER_INLINE() if(--polling_counter < 0)polling_handler()


(3) Write enough of your application in an interpreted language with
an explicit-control interpreter or threaded-code driver (e.g. MIT C-SCHEME)
such that the interpreter can run for a limited amount of time inside a 
callback or work procedure, and then suspend itself, saving its state for
processing next time through the XtAppMainLoop(context).
 Advantage: Elegant. Simple.
 Disadvantage: Technique cannot be retrofited into existing applications
 written in C, FORTRAN, or other language, without translating the code to
 Scheme, Forth, or whatever.

(4) Implement a stack-group or light-weight-process mechanism inside your
application operating-system-process context. Your XtWorkProc will run
for a certain amount time and a timer signal with interrupt it and 
suspend the process by the usual register/stack context switching.
 Advantage: Any existing application can be forcibly retrofitted using
 this technique.
 Disadvantage: Using the existing system debugger gets very complicated,
 porting can be a nightmare, and in most cases all I/O calls have to be
 encapsulated and suspended if needed. Basically you are writing and 
 maintaining your own little operating system.
 * Also, has potential reentrancy problems that could be worse than in #2.