| iMatix home page
| << | < | > | >>
SMT Logo SMT
Version 2.81

Using The SMT API In A Foreign Program

In an SMT application there will always be some foreign programs. Some examples are:

It may make sense in some applications to write all programs as foreign. For instance, you could use the SMT kernel simply to send events between programs without using the multithreading facilities.

Writing A Stub Program

When you build a new SMT application you must also write a STUB program (the main() function). The stub program usually does this:

When you compile and link the stub, you create the executable program for the application.

Managing A Floating Event Queue

An interface between a native program (or a thread) and a foreign program consists of at least an event queue in either direction. The SMT kernel automatically handles the event queue for the native program. You must handle the other event queue yourself:

       Foreign                               Native
   .--------------.                     .--------------.
   : event_send() :-----------> ()()()():              |
   :              |()()()() <-----:-----: event_send() |
   `=============="    :          :     `=============="
                       :        normal event queue
                       `----- floating event queue

Figure: Managing a floating event queue

The program that sends an event does not know whether the event queue is floating or not, although it can find this out if it has to, by examining the queue object. The difference between a floating event queue and a normal event queue is that you must get events off a floating event queue yourself. You can use the API function calls:

event accept()
Accept the next event from an event queue.
event reject()
Reject the next event from an event queue.
event expire()
Expire the next event from an event queue.
event discard()
Discard the next event from an event queue.
event iterate()
Find the next event in an event queue.
event destroy()
Destroy a specific event.

You can use methods if you need to. This can be a convenient way of translating event names into internal numbers of some sort. For instance, if you design the foreign program using the standard Libero C schema, you can use methods to translate event names into internal numbers, much as the SMT kernel does for a native program. This is (more or less) the SMT kernel code that does this translation:

    EVENT   *event;             /*  Event information block     */
    EVENT   *deliver_event;     /*  Event to deliver            */
    METHOD  *method;            /*  Method information block    */
    THREAD  *active;            /*  Thread in active list       */
    int     top_priority;       /*  Highest event priority      */
    int     event_number;       /*  Number for event to deliver */

    /*  Get event to deliver - find event with highest priority */
    top_priority  = -1;
    deliver_event = NULL;
    event = queue-> events.next;
    while ((NODE *) event != &queue-> events)
      {
        /*  Lookup method; if method not declared, reject event */
        method = method lookup (agent, event-> name);
        if (method == NULL)
          {
            /*  Reject this event, but keep place in queue...   */
            sendfmt (&console, "ERROR",
                     "Event %s not declared by %s",
                      event-> name, agent-> name);
            event = event-> next;
            event reject (queue, event-> prev);
            continue;           /*  Process this new event      */
          }
        if (method-> priority > top_priority)
          {
            deliver_event = event;
            event_number  = method-> event_number;
            top_priority  = method-> priority;
          }
        event = event-> next;
      }
    if (deliver_event)
      {
        /*  Deliver event, move thread to active queue          */
        thread-> event          = event accept (queue,
                                  deliver_event);
        thread-> the_next_event = event_number;
        thread-> active         = TRUE;
      }

Executing The Application

The main() function in an executable is a foreign program. Since a foreign program is external to the multithreading process of the SMT kernel, control must pass back and forwards between the SMT kernel and the foreign program. Typically this is a loop like this:

To do the second step, the foreign program calls smt exec full(). This function runs all the agent threads until there are no more events left to deliver, or active threads.

Sometimes it is better to call smt exec step() repeatedly. This function delivers events, but only executes the first active thread. This function provides a finer-grain control. For instance, if the application loops because two threads send each other events in a never-ending loop (usually a programming error), the smt exec full() call will never return, while the smt exec step() call will return each time that the kernel switches between the threads.


| << | < | > | >> iMatix Copyright © 1996-99 iMatix Corporation