Main Page   Interface   Data Structures   File List   Data Fields   Globals  

FORK.h File Reference

The FORK utilities create and manage a buffered queue between two tasks. More...

#include "BBC/LLI.h"
#include "BBC/TASK.h"

Data Structures

struct  _FORK_msg_hdr
 All messages queued by the FORK routines must be prefaced by this controlling structure. More...

struct  _FORK_msg_sys
 A predefined message consisting of a FORK_msg_hdr and a single 32-bit location to hold the contents. More...


Typedefs

typedef _FORK_fcb FORK_fcb
 Typedef for struct _FORK_fcb.

typedef _FORK_msg_hdr FORK_msg_hdr
 Typedef for struct _FORK_msg_hdr.

typedef _FORK_msg_sys FORK_msg_sys
 Typedef for struct _FORK_msg_sys.

typedef enum _FORK_type FORK_type
 Typedef for the enum _FORK_type. More...

typedef enum _FORK_cb_status FORK_cb_status
 Typedef for enum _FORK_cb_status.

typedef void * FORK_cb_prm
 Typedef for the FORK callback parameter. More...

typedef FORK_cb_status(* FORK_cb_rtn )(FORK_cb_prm context, struct _FORK_msg_hdr *msg_hdr)
 Signature of the FORK callback handler. More...


Enumerations

enum  _FORK_type {
  FORK_K_TYPE_NON_BLOCKING = LLI_K_TYPE_NON_BLOCKING,
  FORK_K_TYPE_FIFO_BLOCKING = LLI_K_TYPE_FIFO_BLOCKING,
  FOKR_K_TYPE_PRIORITY_BLOCKING = LLI_K_TYPE_PRIORITY_BLOCKING
}
 Enumerates the different blocking types. This determines the behaviour one attempts to remove an system message from an empty list. More...

enum  _FORK_cb_status {
  FORK_C_DESTROY = -2,
  FORK_C_ABORT = -1,
  FORK_C_CONTINUE = 0
}
 Enumerates the status of the call back routine. More...


Functions

int FORK_fcb_sizeof (void)
 Returns the size, in bytes, of a FORK Control Block. More...

int FORK_create (FORK_fcb *fcb, FORK_cb_rtn def_handler, FORK_cb_prm ctx, FORK_cb_prm tmo_ctx, int tmo, FORK_msg_sys *msg_blks, int msg_cnt, FORK_type type, const TASK_attr *attr)
 Creates a FORK message que. More...

int FORK_destroy (FORK_fcb *fcb)
 Destroys a FORK que. More...

int FORK_qsys (FORK_fcb *fcb, FORK_cb_rtn handler, void *contents, int tmo)
 Ques a message using the internal FORK message blocks. More...

int FORK_qusr (FORK_fcb *fcb, FORK_cb_rtn handler, FORK_msg_hdr *msg_hdr)
 Ques a user composed message. More...


Detailed Description

The FORK utilities create and manage a buffered queue between two tasks.

The FORK routines provide a convenient way to spread work across to tasks or threads. A interlocked message que is created between the task calling task of FORK_create () and a task/thread created by the FORK_create(). Messages can be placed on this que by any task that has access to the que through the Fork Control Block. In this sense, it is a multi-writer, single-reader half-duplex communication link.

These routines serve much the same purpose as the VxWorks semQ routines with some important advantages.

1. These routines allow one complete control over the memory containing the messages.

The VxWorks send routine merely returns a failure status code when one memory exists to buffer a new message. This causes two problems for the programmer. The first is, exactly when does should one try again. The only recourse here, aside from the non-answer of polling until success, is to provide a synchronizing mechanism. One could give a semaphore when a message was consumed. This seems kludgy, since the semaphore is not tied explicitly to the message que and overly complicated to use. T

The second problem is what does the user do when blocking is not an option, as in an interrupt service routine. The FORK routines allow the user to pre-allocate the message buffer before committing to servicing an interrupt. This ensures that the necessary resources are in hand.

2. The burden of creating the receiving task is taken on by the FORK_create() routine.

Since the metaphor of the FORK routines is to transparently fork the execution path, this seems more natural than manually creating an task/thread to handle the messages. In most cases, this is all the create task is going to do, ie pend on a message que and service the incominig messages.

3. The messsage to be queued is not copied twice as it is in the VxWorks routines (once when sending and once when receiving). This is a direct consequence of allowing the user to do his own management of the message buffers.

USAGE
-----
The user first creates the FORK que by calling FORK_create(). FORK_create() allows control overall the parameters of the FORK que, including the attributes of the FORK servicing task. The user also has the option having the FORK routines create an internally managed pool of message buffers.

A queued message always consists of two quantities, a routine to handle the message and the message contents itself. If the internal message pool, referred to here as the system pool, is used, the contents of the message are limited to a single 32 bit number. If the user chooses to que his own messages, the contents can be any size he wishes, his own obligation is to preface the message with a FORK_msg_hdr structure. Messages of varying sizes and types, ie both user and system messages, can be queued to the same FORK que. The deallocation of user messages are the responsibility of the user, while system messages are freed immediately after the dispatch routine finishes its processing.

This latter design choice has only a slight impact on performance, since, in theory, the dispatch routine could release the message memory earlier. However, given the single reader nature of the FORK utilities, only one such buffer can be outstanding at an given time. The truly concerned user can avoid this limitation by using only message buffers that he manages.

EXAMPLE
-------


    FORK_fcb *fcb;
    int      size;

    / * Allocate 10 message blocks for the FORK ques internal pool * /
    FORK_msg_sys msg_blks[10];
    int          msg_blk_cnt = sizeof (msg_blks) / sizeof (*msg_blks);

    size = FORK_fcb_sizeof ();              / * Size of Fork Control Block  * /
    fcb  = (FORK_fcb *) malloc (size);      / * Allocate the memory for it  * /

    / * Create the fork que                                                 * /
    status = FORK_create (fcb,              / * Fork Control Block to init  * /
                          normalPrint,      / * Default handling routine    * /
                          forkParameter,    / * Parameter passed to handler * /
                          forkTmoParameter, / * Parameter passed if timeout * /
                          timeout,          / * How long to pend before tmo * /
                          msg_blks,         / * A source of message blocks  * /
                          msg_blk_cnt,      / * Number of messge blocks     * /
                          FORK_K_TYPE_FIFO_BLOCKING,
                                            / * FIFO style blocking when    * /
                                            / * allocating system messges   * /
                          NULL);            / * Use default task attributes * /

    status = FORK_qsys (fcb, NULL,      "Hello World\n",   FORK_K_WTO_FOREVER);
    status = FORK_qsys (fcb, boldPrint, "Goodbye World\n", FORK_K_WTO_FOREVER);

    }
    
    int normalPrint (void *parameter, FORK_msg_sys *msg)
    {
       fputs (msg->contents);
       return FORK_C_CONTINUE;
    }

    int boldPrint (void *parameter, FORK_msg_sys *msg)
    {
      printf ("%s", BOLD_ESC_SEQUENCE);
      fputs (msg->contents);
      printf ("%s", NORMAL_ESC_SEQUENCE);
      return FORK_C_CONTINUE;
    }
   

The usual precautions should be heeded. For example, in this example, not allowing the creating task to terminate when messages are still on the que. Since the memory is from stack, that would be bad.


Typedef Documentation

FORK_cb_prm
 

Typedef for the FORK callback parameter.

This parameter is specified when calling FORK_create() and is passed transparently into the user's callback handler.

FORK_cb_rtn
 

Signature of the FORK callback handler.

Defines the signature for the user callback & parameter

        status = (*cb_rtn) (FORK_cb_prm cb_prm, FORK_msg_hdr *msg_hdr)
        
   Where:
          cb_prm: The value of the context parameter passed into the
                  FORK_create routines.
  
         msg_hdr: A pointer to the message header. This pointer will,
                  in all likelihood, be recasted into a pointer to
                  the specific style of message one is expecting.
  
  
    RETURN VALUE:  FORK_C_CONTINUE, keep going.
                   FORK_C_ABORT,    abort the FORK task.
                   FORK_C_DESTROY,  abort the FORK task and destroy the FORK q
                   
   

FORK_type
 

Typedef for the enum _FORK_type.


Enumeration Type Documentation

enum _FORK_cb_status
 

Enumerates the status of the call back routine.

This enumerates the return value of the user's dispatch callback handler. Basically one can tell the FORK pend routine to do one of three things, pend for another message, FORK_C_CONTINUE, abort, FORK_C_ABORT, or FORK_C_DESTROY, abort the FORK que and destroy the FORK que context. Aborting the FORK pend operation kills the FORK servicing task, so be careful that all context has been cleaned up before issuing this return code. It is up to the user to clean-up these resources.

Warning:
The FORK shutdown procedure is not well-defined at this time so avoid using this feature for a while.
Enumeration values:
FORK_C_DESTROY  Kill the FORK task and the FORK context
FORK_C_ABORT  Kill the FORK task, but not the FORK context
FORK_C_CONTINUE  Continue normal processing

enum _FORK_type
 

Enumerates the different blocking types. This determines the behaviour one attempts to remove an system message from an empty list.

Enumeration values:
FORK_K_TYPE_NON_BLOCKING  No blocking mechanism available
FORK_K_TYPE_FIFO_BLOCKING  Use FIFO blocking order
FOKR_K_TYPE_PRIORITY_BLOCKING  Use PRIORITY blocking order


Function Documentation

int FORK_create FORK_fcb   fcb,
FORK_cb_rtn    def_handler,
FORK_cb_prm    ctx,
FORK_cb_prm    tmo_ctx,
int    tmo,
FORK_msg_sys   msg_blks,
int    msg_cnt,
FORK_type    type,
const TASK_attr *    attr
 

Creates a FORK message que.

Parameters:
fcb  The FORK Control Block to initialize
def_handler  The address of a default FORK handler. This routine will be called back in one of two circumstances.

1. The user does not provide an explicit
routine queing the message.
2. A timeout occurs

ctx  Parameter passed transparently to the user's callback handler, except in the case of a timeout.
tmo_ctx  Parameter passed transparently to the user's callback routine in case of a timeout. The user may use this parameter to distinguish a timeout condition from a normal message. (The message block will also be NULL in this case.)
msg_blks  A source of internal message blocks. This may be specified as NULL.
msg_cnt  The number of msg_blks. This may be specified as 0. Note that this parameter is ignored if msg_blks is specified as NULL.
type  The blocking type to use when attempting allocate a message from the system queue.
attributes  The attributes to use when creating the FORK servicing task.
Returns:
Status
This routine creates the FORK message que and its associated task. The def_handler will be used as the callback handler when a message is queued without an explicit handler, see FORK_qsys() and FORK_quser(). It is also used when a timeout occurs.

int FORK_destroy FORK_fcb   fcb
 

Destroys a FORK que.

Parameters:
fcb  The Fork Control Block of the FORK que to destroy
Returns:
Status
Releases all the internal resources used by the FORK que. It does not release either the memory associated with any potential internal pool of message blocks that the FORK routines may be managing on behalf of the user, nor does it release the memory associated with thr Fork Control Block itself. Both these are user providef blocks of memory and, therefore, user managed blocks of memories.

Warning:
As with all delete operations, care must be taken to ensure it is safe to destroy the FORK que.

FORK_fcb_sizeof void   
 

Returns the size, in bytes, of a FORK Control Block.

Returns:
The sizeof of a fork control block
Gets the size of a FORK CONTROL BLOCK. This allows the user to allocate and control the FORK CONTROL BLOCK without making its internal structure known.

int FORK_qsys FORK_fcb   fcb,
FORK_cb_rtn    handler,
void *    contents,
int    tmo
 

Ques a message using the internal FORK message blocks.

Parameters:
fcb  The Fork Control Block to que the message to
handler  A callback handler. This may be specified as NULL, in which case, the default handler established by FORK_create(), will handle the message.
contents  A single 32-bit value representing the message contents.
tmo  A timeout value to be used in case there are no message blocks available. The values FORK_K_WTO_NO_WAIT (0) and FORK_K_WTO_FOREVER can be used here. In the future a real timeout value will be implemented.
Returns:
Status
Ques a message to the FORK message que using the internal system message pool. System messages are limited to queing a single 32-bit number. Of course one can always use this to que a pointer to another data structure, the user should consider FORK_qusr(), to que a more complicated message without absorbing a level of indirection.

Note that because the message is internally allocated it may be possible that this list is exhausted. A timeout parameter is provided to handle this situation.

int FORK_qusr FORK_fcb   fcb,
FORK_cb_rtn    handler,
FORK_msg_hdr   msg_hdr
 

Ques a user composed message.

Parameters:
fcb  The Fork Control Block to que the message to
handler  A callback handler. This may be specified as NULL, in which case, the default handler established by FORK_create(), will handle the message.
msg_hdr  Pointer to the message to que. It is mandatory that all queued messages are prefaced by a standard message header block
Returns:
Status
Ques a user defined message. This routine behaves in much the same manner as FORK_qsys(), except the message being queued is controlled almost entirely by the user. (The except part, is that the message must be prefaced by a standard message header.)

For the extra work involved in using this routine, the user gets to control his own memory allocation and the exact contents of the message. This means that there is almost no case, other than an internal corruption, under which this routine can fail.


Generated on Fri Mar 1 16:55:28 2002 by doxygen1.2.13.1 written by Dimitri van Heesch, © 1997-2001