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

 

thread_create

#include "smtlib.h"
THREAD *
thread_create (
    const char *agent_name,             /*  Name of agent                    */
    const char *thread_name             /*  Create thread with this name     */
)

Synopsis

Creates a new thread, and possibly an event queue for the thread. The caller specifies the agent and thread name. The agent must already be declared using agent declare(). If the agent was defined as a router, you can create multiple threads with the same name. These threads then share the same event queue on an anonymous basis. If the agent was not defined as a router, it is illegal to create multiple threads with the same name unless the name is empty (meaning "" or NULL). The function automatically creates an event queue for the thread when required. Returns a pointer to the created THREAD block, or null if there was an error. In that case, sets smt_errno to one of:
SMT NOTREADY smt_init() was not called, or failed
SMT OUTOFMEMORY Not enough heap memory left
SMT NOSUCHAGENT The agent was not declared
SMT AGENTNOTREADY The agent is not initialised
SMT TOOMANYTHREADS Tried to exceed the maximum permitted threads
SMT THREADEXISTS The thread already exists
Attaches the thread to the active thread list.

Source Code - (smtlib.c)

{
    SYMBOL  *dict_entry;                /*  Dictionary symbol                */
    AGENT   *agent;                     /*  Agent information block          */
    QUEUE   *queue;                     /*  Queue information block          */
    THREAD  *thread;                    /*  Created thread block             */
    char    *full_name;                 /*  Full thread name                 */

#if (defined (SMT_TRACE))
    trace ("thread_create: agent=%s thread=%s", agent_name, thread_name);
#endif
    ASSERT (agent_name);
    if (!smt_alive)                     /*  If SMT API was not correctly     */
      {                                 /*    initialised, forget it         */
        smt_errno = SMT_NOTREADY;
        return (NULL);
      }

    /*  Find agent, quit if there was an error                               */
    if ((agent = agent lookup (agent_name)) == NULL)
        return (NULL);

    /*  Check that we're allowed to create a new thread                      */
    if (agent-> max_threads > 0
    &&  agent-> max_threads == agent-> cur_threads)
      {
        smt_errno = SMT_TOOMANYTHREADS;
        return (NULL);
      }

    /*  Simple check that agent has been initialised                         */
    if (agent-> initialise == NULL)
      {
        smt_errno = SMT_AGENTNOTREADY;
        return (NULL);
      }

    /*  Treat a NULL thread name as an empty string                          */
    if (thread_name == NULL)
        thread_name = "";

    /*  Check if the thread already exists                                   */
    full_name  = get_entity_name (agent_name, thread_name);
    dict_entry = sym_lookup_symbol (dict, full_name);
    queue      = NULL;                  /*  No queue created yet             */
    if (dict_entry)
      {
        /*  If it's a router, we'll use the same queue                       */
        if (agent-> router)
            queue = ((THREAD *) (dict_entry-> data))-> queue;
        else
        if (thread_name [0])            /*  Otherwise it's an error if the   */
          {                             /*    thread was given a name        */
            smt_errno = SMT_THREADEXISTS;
            return (NULL);
          }
      }
    if (!queue)                        /*   Create new queue in agent        */
        queue = queue create (agent, 0);

    /*  Now create entry for the thread                                      */
    dict_entry = sym_create_symbol (dict, full_name, NULL);
    if (dict_entry == NULL)
      {
        if (queue)                      /*  Clean-up nicely                  */
            queue destroy (queue);
        smt_errno = SMT_OUTOFMEMORY;
        return (NULL);
      }

    /*  Allocate a THREAD block and attach it to the queue's thread list     */
    /*  We also allocate the TCB and subdialog stack if that is required     */
    thread = (THREAD *) node_create (&queue-> threads, sizeof (THREAD));
    if (thread)
      {
        thread-> tcb      = agent-> tcb_size > 0?
                            mem_alloc (agent-> tcb_size):
                            NULL;
        thread-> LR_stack = agent-> stack_size > 0?
                            mem_alloc (agent-> stack_size * sizeof (event_t)):
                            NULL;
      }
    if (thread == NULL)
      {
        sym_delete_symbol (dict, dict_entry);
        if (queue)                      /*  Clean-up nicely                  */
            queue destroy (queue);
        smt_errno = SMT_OUTOFMEMORY;
        return (NULL);
      }

    /*  Point the dictionary entry to the thread information block            */
    dict_entry-> data = thread;

    /*  Now initialise the thread fields and list heads                       */
    thread-> symbol     = dict_entry;
    thread-> name       = mem_strdup (thread_name);
    thread-> queue      = queue;
    thread-> thread_id  = agent-> thread_tally++;
    thread-> animate    = agent-> animate;
    thread-> left       = thread;
    thread-> right      = thread;
    thread-> event      = NULL;         /*  Last event for thread            */

    cur_threads++;                      /*  Keep count of threads            */
    agent-> cur_threads++;
    if (agent-> top_threads < agent-> cur_threads)
        agent-> top_threads = agent-> cur_threads;

    activate_thread (thread);           /*  Move thread to active list       */
    thread-> state    = SMT_THREAD_ACTIVE;
    thread-> LR_state = SMT_NULL_STATE;
    return (thread);
}

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