| Prev | Next | Start of Chapter | End of Chapter | Contents | Glossary | Index | Comments | (7 out of 25)

Using Procedures

Using G2 procedures is similar to using procedures in any programming environment. G2 also provides some capabilities beyond those ordinarily available. These allow you to optimize and control procedure execution in various ways, as described later in this section.

Invoking a Procedure

You can invoke a procedure from within another procedure by using either a start action or call statement.

The start action invokes a procedure and runs it asynchronously. It tells G2 to schedule the new procedure for execution, then continue processing the current procedure. You can also use the start action to invoke a procedure from within a rule, a button, or any other context where you can execute an action. For more information about the start action, see start.

The call statement invokes a procedure and runs it synchronously. It tells G2 to invoke the new procedure and wait until the procedure returns before continuing to execute the calling procedure. Call is a procedure statement, not an action: you can use it only in the body of a procedure. For more information on the call statement, see call.

Passing Arguments to a Procedure

Whenever you invoke a procedure, you must pass it the correct number and type of arguments. When a procedure is defined, the arguments are specified in the procedure header. For example:

The plant-record procedure has two arguments, whose local names are plant-name and inventory-total. The plant-name is of type text, and inventory-total is of type quantity. You could invoke the plant-record procedure like this:

Any argument to a procedure can be given literally or as an expression that evaluates to an item or value of the correct type. Thus you could have specified a text parameter as the plant-name, in which case, you would not surround it with double quotation marks. G2 would then use the value of the text parameter as the value of the plant-name.

For example, if SOAP-1 is a text variable or text parameter whose value is soap-plant-1, then:

is equivalent to the call in the previous example.

Accessing Variables in a Procedure

In order to reference the value of a variable, a procedure must use a collect data statement whether or not the variable has a value at the time of the reference. For details, see collect data.

Memory Management in Procedures

When a procedure creates an item, that item is not automatically deleted when the procedure exits: the item persists indefinitely until explicitly deleted with a delete action. Therefore, a procedure must delete every item that it creates unless the item is specifically intended to persist and be used elsewhere in the KB.

If this requirement is not met, and undeleted items accumulate without limit, they will eventually consume all memory and abort G2. For additional information, see:

Allowing Other Processing

Concurrent processing during procedure execution can allow other processes to change data used by the procedure, with unpredictable results. For an example, see Allowing Other Processing During List and Array Iteration.

To prevent such problems, G2 by default executes a procedure without interruption. However, uninterrupted procedure execution prevents G2 from accomplishing any other tasks, such as serving data servers and user interfaces, performing tasks for other procedures and for rules, and so on.

G2 provides two mechanisms for preventing uninterrupted execution from locking out other processing to a harmful extent:

Wait States

A procedure can enter a wait state when it executes any of the following statements:

Whether the procedure enters a wait state when one of these statements occurs can depend on the conditions that exist when G2 executes the statement. G2 processes each of the statements as follows:

Processing During Wait States

The fact that G2 enters a wait state does not guarantee that it will execute all or any scheduled tasks before the wait state ends. If the wait was predicated to end with a particular event, such as a variable obtaining a value or a time interval passing, the procedure can be sure that the specified outcome has occurred, or the wait would not have ended. Beyond that, the procedure should make no assumptions about what did or did not happen while it waited.

Using Wait States Cautiously

When a wait state ends and the interrupted procedure resumes execution, the environment in which it executes may have changed in ways that invalidate the procedure's assumptions. Be sure to revalidate the environment as needed before continuing execution of the procedure.

Statements that can cause wait states should not be inserted into procedures without careful consideration of the possible consequences. To prevent concurrency problems, use them only in controlled ways to serve definite purposes.

Limiting Procedure Execution Time

The Uninterrupted-procedure-execution-limit attribute sets a limit on the amount of execution time a procedure can use without in some way allowing other processing to occur. The possible values are:


Caution: Specifying none can be dangerous. If the procedure enters an infinite loop, or otherwise fails to return, it will prevent other processing indefinitely, effectively freezing G2. If this happens, you can stop the procedure only by terminating your G2 process from the operating system.

G2 maintains a tally of the cumulative execution time of each executing procedure. For a given executing procedure, G2 resets this measure only when that procedure, or some procedure called by it, enters a wait state, allowing other processing to occur.

If an executing procedure exceeds its specified execution time limit, G2 signals an error. If no user-defined handler exists for the error, G2 aborts the procedure and posts an error message to the Operator Logbook.

When G2 aborts a procedure that was called by another, it also aborts the caller. Thus procedure timeout in the absence of an error handler aborts the entire procedure stack, not just the procedure that timed out.

For more information, refer to Timing Parameters.

Setting Procedure Priority

The Default-procedure-priority attribute controls the default priority at which G2 executes an asynchronously invoked procedure. For information on priorities, see Chapter 46, Task Scheduling.

The default priority is 6. You should accept this default unless you have a specific reason to change it. If you need to change it, set the attribute to an integer between 1 and 10 that indicates the priority at which you want the procedure to run.

Three different factors can set the priority at which a procedure executes:

  1. A called procedure runs at the same priority at which its caller is running, irrespective of the value of its Default-procedure-priority attribute.

  2. A started procedure runs by default at the priority declared in its Default-procedure-priority attribute.

  3. You can override the default priority by including the clause at priority integer-expression in the start statement that invokes the procedure. Thus:

    starts the procedure at priority 2, rather than at the priority given by its Default-procedure-priority attribute.

Debugging a Procedure

The Tracing-and-breakpoints attribute allows you to set tracing and breakpoints on the procedure. G2 provides three techniques for debugging procedures:

For information on debugging, see Chapter 42, Debugging and Tracing.

Displaying a Procedure's Invocation Hierarchy

You can use Inspect to display on a workspace:

Instructions appear under Showing Procedure Invocation Hierarchy.

Inlining a Procedure

A procedure declared as inlineable exists as a separate item, but is compiled as part of the calling code when called from another procedure. Inlining a procedure improves performance by:

However, inlined procedures increase the size of the executable code, because the code for the procedure is copied redundantly to every point where the procedure is invoked. Inlining is best for small procedures that are called frequently, typically from a loop that iterates many times.

Embedded code is incompatible with asynchronous and recursive invocation, so the code for an inlineable procedure is actually inlined only for a nonrecursive call. Inlineable procedures exist as ordinary procedure items; starts and recursive calls to them are handled just as if the procedure were not inlineable.

Declaring a Procedure as Inlineable

When declaring a procedure as inlineable, you must also use the configuration clause: stable-for-dependent-compilation.

To declare that a procedure can be inlined:


Tip: As with other configurations, the stable-for-dependent-compilation configuration statement can be applied to a workspace. Whenever configurations are applied to workspaces, their effects propagate to every applicable item upon the workspace (procedures in this case), and all item subworkspaces.

Recompiling an Inlineable Procedure

When you change the Item-configuration of a procedure to include these properties, the Notes attribute of the procedure changes to read:

To recompile the inlineable procedure:

  1. Choose edit from the table item menu of the procedure attribute table. G2 displays this dialog, because the procedure has been declared as stable:


  2. Click OK to continue.

  3. Save the edited procedure to recompile it. The procedure Notes status will be OK.


Note: After making a procedure inlineable and recompiling it, other procedures that call the inlined procedure must be recompiled to incorporate the inlineable code. You can recompile a single procedure by editing it in the Text Editor and saving any changes, or recompile your entire KB using Inspect.

Testing for an Inlined Procedure

You can test whether a procedure has been inlined through the G2 Tracing facility.

To test for an inlined procedure:

  1. In the Debugging Parameters system table, change the Tracing-and-breakpoints-enabled? attribute to yes.

  2. Change the value of the Tracing-message-level attribute to:

  3. Run the procedure that calls the inlined procedure. If the inlined code has been incorporated into the calling procedure, the inlined procedure will not appear in the trace messages.

For a further discussion on using these configuration statements, see Using Compilation Configurations.

Creating Procedure Invocations

A procedure invocation is an item that represents an instance of an executing procedure. You can put procedure invocations into lists, assign them to participate in relations, and manipulate them as you would any other item.

The Class-of-procedure-invocation attribute specifies whether G2 automatically creates a procedure invocation when a procedure is called or started. Possible values are none and procedure-invocation. The default is none.

If the Class-of-procedure-invocation is specified as procedure-invocation, G2 automatically creates a procedure invocation each time that procedure is invoked from a start action or call statement. G2 creates a separate procedure invocation each time the procedure is invoked, so a procedure that is recursive or runs concurrently with itself can have more than one procedure invocation at the same time. G2 automatically deletes a procedure invocation when the procedure returns.

For information on referencing procedure invocations in expressions, see the example The Procedure Invocation Associated With the Procedure Containing the Expression.

Aborting a Runaway Procedure

When a procedure goes into an infinite loop that never enters a wait state, only expiration of the uninterrupted procedure execution time limit can abort it, as described under Limiting Procedure Execution Time. If no such time limit is in effect, the only recourse is to abort G2 itself from the operating system command level.

If the procedure does enter a wait state at some point in the loop, you can use several techniques to abort the procedure:

When you use one of these techniques, G2's response may not be immediate, because G2 cannot process the operation until the runaway procedure enters a wait state.


Caution: When you abort a runaway procedure, the KB may be left with undeleted items or incorrect global data that the procedure would have cleaned up if it had exited normally. If any such problem is possible, reset the KB before you rely on it to function correctly.

Expressions for Procedures

These are the expressions to use with procedures.

The Procedure Containing the Expression

this procedure 
-> procedure
This expression produces the procedure within whose invocation G2 evaluates this expression. For example, the announce-self procedure creates and places a message upon its workspace, then deletes that message 10 seconds later:

The Procedure Invocation Associated With the Procedure Containing the Expression

This expression produces the executing procedure invocation within which G2 evaluates this expression.

Specify this expression only in the text of a procedure or method whose Class-of-procedure-invocation attribute has the value procedure-invocation. Invoking such a procedure causes G2 to create a procedure invocation item. For more information about procedure invocations, see Creating Procedure Invocations.

For example, the next figure shows a workspace that contains two lists, an initially rule, and the view-invocation procedure. The initially rule starts the view-invocation procedure once for each list that exists.


Each invocation of view-invocation causes G2 to create one procedure-invocation. view-invocation transfers this procedure-invocation to the workspace of the list passed as its argument and graphically aligns its icon with that list's icon. Once per second for several seconds, view-invocation changes the icon-color of this procedure-invocation to indicate that it is active.

| Prev | Next | Start of Chapter | End of Chapter | Contents | Glossary | Index | Comments | (7 out of 25)

Copyright © 1997 Gensym Corporation, Inc.