swirl
Guide to OmniMark 8   OmniMark home
docs home 
IndexConceptsTasksSyntaxLibrariesLegacy LibrariesErrors
 
Prerequisite Concepts     Related Syntax  

Co-routines, managing

In certain cases, OmniMark creates co-routines in order to efficiently stream data within an OmniMark program. Most of the time, this behavior is handled completely automatically and there is no need for the programmer to worry about it. However, there are occasions in which the behavior of co-routines may lead to unexpected behavior in your program. This topic will help you understand when co-routines are active and what consequences they have for your program.

Co-routining occurs when you have one routine in you program that provides a stream of data and a second routine that consumes that data. Under normal circumstances, the first routine would run to completion, its output would be buffered, and when it was finished, the second routine would start and consume the data from the buffer. This is what happens, for instance, when you call a string returning function in OmniMark:

  define string function get-some-text
   as
     local stream temp-buffer
     open temp-buffer as buffer
     using output as temp-buffer
      repeat for integer i from 1 to 1000
        output "%d(i): abcdefghijklmnopqrstuvwxyz%n"
      again
     close temp-buffer
     return temp-buffer
     
  process
     submit get-some-text
     
  find  lc+ => letters
     output "%ug(letters)"

In this program, the entire output of the function, the alphabet repeated one thousand times, is buffered in the stream temp-buffer and returned to the submit statement in a single block. However, if you replace the string function with a string source function you will get co-routining behavior:

  define string source function make-some-text
   as
     repeat for integer i to 1000
        output "%d(i): abcdefghijklmnopqrstuvwxyz%n"
        log-message "input"
     again
  
  process
    using output as file "out.txt"
     submit make-some-text
  
  find lc+ => l
     output "%ug(l)"
     log-message "main"

In this case, the string source function runs as one co-routine and the calling function runs as another co-routine. Every time the output statement is executed in the string source function, control is passed to the calling program where the submit statement processes the data returned and then passes control back to the string source function. Control is passed back and forth between the two routines until the string source function is completed. You can see this behavior very clearly by tracing the sample program in the debugger or by running it at the command line and observing how the log-message alternatively prints "input" and "main" on the console.

When you write a program that processes data that is fed to a markup parser, either using a string source function or a cross-translate or up-translate aided translation type, the markup parser runs as a co-routine.

You can use a string source to generate or pre-process markup that is to be sent to a parser. When an string source function is called in a parse context, the string source function and the parser run as co-routines. That is, the string source function is executed incrementally and streams its output to the parser incrementally. Execution passes back and forth between the parser and the string source function until the entire input has been processed. This avoids buffering the entire output of the string source function before the parser starts. This saves computer resources and improves performance. You can process very large amounts of data without running into resource problems.

In the following example, the string source function parser-feeder generates an XML document by submitting a source. The markup is generated partly in the function itself and partly by find rules fired as a result of the submit statement. The output of the function and the find rules becomes the input to the parser. Element rules then transform the XML into HTML.

  define string source function parser-feeder as
     output "<greeting>"
     submit "Hello world."
     output "</greeting>"
  
  find "world" => planet-name
     output "<planet>"
         || planet-name
         || "</planet>"
  
  process
     do xml-parse
      scan parser-feeder
        output "<HTML><BODY>%c"
            || "</BODY></HTML>"
     done
  
  element "greeting"
     output "<P>%c</P>"
  
  element "planet"
     output "<B>%c</B>"

Other advantages of using string source functions include:

Debugging co-routines

In rare cases you may experience problems with the use of string source functions or the cross-translate or up-translate aided translation types because of the way OmniMark coordinates the activities of co-routines.

When you use co-routines, you have two processes running cooperatively within a single program. OmniMark runs each process in a separate processing domain. Some resources are owned by one domain or the other, while others are shared between the two domains.

If you experience an error in a program that uses co-routines, the answer may be found in the following:

Note that it may not always be obvious which co-routine a certain piece of code is running in. For instance, a find rule could be fired either by a submit in an string source function or by a submit in an element rule. That rule would be running in one domain in the first case and in the other domain in the second case.

If you write code that depends on the timing of the switching between the string source function and the parser, you may need to be aware of the rules OmniMark uses when switching domains.

The old form of input function

In versions of OmniMark prior to version 7, an input function was an action function which was called as an input function by adding the keyword input to the parser invocation:

  define function parser-feeder as
     output "<greeting>"
     submit "Hello world."
     output "</greeting>"
  
  find "world" => planet-name
     output "<planet>"
         || planet-name
         || "</planet>"
  
  process
     do xml-parse
      scan input parser-feeder
        output "<HTML><BODY>%c"
            || "</BODY></HTML>"
     done
  
  element "greeting"
     output "<P>%c</P>"
  
  element "planet"
     output "<B>%c</B>"

This form is deprecated but is supported for backward compatibility.

Prerequisite Concepts
   Data types
   Functions
 
  Related Syntax
   do markup-parse
   do sgml-parse
   do xml-parse
 
 

Top [ INDEX ] [ CONCEPTS ] [ TASKS ] [ SYNTAX ] [ LIBRARIES ] [ LEGACY LIBRARIES ] [ ERRORS ]

OmniMark 8.2.0 Documentation Generated: March 13, 2008 at 3:25:49 pm
If you have any comments about this section of the documentation, please use this form.

Copyright © Stilo International plc, 1988-2008.