home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 420.lha / OdinLibrary_v2.7 / odin.doc < prev    next >
Encoding:
Text File  |  1990-10-01  |  19.1 KB  |  544 lines

  1. odin.doc, version 2.7, 9-Sep-90, Release 2
  2. Created 3-Jul-90 by Peter Ørbæk (C)
  3.  
  4.                       Documentation for odin.library
  5.                       ------------------------------
  6.  
  7.    The  main  intention  of  this  library  is  to provide an easier way to
  8. accomplish  Inter-Process  Communications  (IPC)  on  the  Amiga using C or
  9. assembler.  Most of the functions provided are inspired by Linda, an add-on
  10. language for C and other high-level languages, which provides a simple, yet
  11. poverful way to do IPC.
  12.  
  13.    Instead  of  implementing  the  Linda language directly, I have chosen a
  14. more  pragmatic  approach  to  provide much of the same functionallity, but
  15. without all of the theoretic elegance in Linda.
  16.  
  17.  
  18.                            Envelopes and e-space
  19.                            ---------------------
  20.  
  21.    The  central  concept  in  odin.library is the envelope.  An envelope is
  22. used  to  pass  information  between  processes,  and they are used to hold
  23. information  residing  in  e-space.   In  C an envelope is a structure that
  24. begins  with  the  Envelope-structure defined in odin.h.  This structure is
  25. explained below.
  26.  
  27.    There's  no  restrictions  on  the contents of an envelope, the contents
  28. being  whatever  comes after the Envelope-structure.  The contents need not
  29. be  contigous  in  memory.   You  can  specify  a  C-function to serve as a
  30. copying-routine for each envelope.
  31.  
  32.    The  e-space  is  an  abstact  storage  containing  envelopes  and their
  33. contents.  Envelopes are identified by a name, ie.  a null-terminated ASCII
  34. string.  Envelopes can be put into and retrieved from e-space via the name.
  35. E-space  can contain many envelopes with the same name.  Envelopes with the
  36. same  name  will  be retrieved in the same order as they have been inserted
  37. into e-space, forming a queue.
  38.  
  39.    To  prevent  two different programs from unintentional interference with
  40. each others envelopes a naming convention should be applied.  My suggestion
  41. is  to  name  envelopes  intended for private use within some internal task
  42. like   this:   "<ProgramName>:<envelopename>"  (this  is  not  used  in  my
  43. examples...).
  44.  
  45.                              Function overview
  46.                              -----------------
  47.  
  48.    You can generate 'unique' envelope-names with the function UniqueName().
  49.  
  50.    Functions   for   general  envelope-management  are:   CreateEnvelope(),
  51. InitEnvelope()  and  DisposeEnvelope().  To put envelopes into e-space use:
  52. Out(),CopyOut()  or  OutEmptyEnvelope().   You  can wait for an envelope to
  53. appear in e-space with:  In(), Rd() and AwaitNamedEnvelope().  You can also
  54. poll  for  the  existence  of  envelopes in e-space with:  Inp(), Rdp() and
  55. PollNamedEnvelope().
  56.  
  57.    You  can  wait  for an envelope to appear in e-space within a given time
  58. with:  TimedIn(), TimedRd() and AwaitTimed(), and you can request that your
  59. task  gets  a message when an envelope with a given name appears in e-space
  60. with:  AsyncIn(), AsyncRd() and AsyncRequest().
  61.  
  62.    New  tasks and processes can be launched by the Eval() function.  Eval()
  63. provides  a simple, yet powerful way to transfer arguments to the new task/
  64. process, and a way to determine when the new task/process is finished.
  65.  
  66.    There  are  also two lower-level functions for creating tasks/processes:
  67. StartTask() and StartProcess().
  68.  
  69.    System requirements to use odin.library is a mere 10K of free memory and
  70. KickStart 33.180 (V1.2) or later.
  71.  
  72.                                The envelope
  73.                                ------------
  74.  
  75.    The  C  structure  for  an  envelope,  defined  in  include/odin.h is as
  76. follows:
  77.  
  78.  
  79.    typedef struct _Env {
  80.       struct MinNode e_link;         /* first a link for use in e-space */
  81.       STRPTR         e_name;         /* the name of this envelope       */
  82.       ULONG          e_len;          /* bytelength of whole envelope    */
  83.       struct _Env *  (*e_copyfunc)();/* opt. C-function for copying     */
  84.       struct _Env *  (*e_proc)();    /* C-func. to call in Eval()       */
  85.    } Envelope;
  86.  
  87.  
  88.    The  e_link  field  is  of  no  interest  for  casual users, and is used
  89. internally to keep track of the envelopes while they float in e-space.  The
  90. e_name  field  points  to  the  namestring.   It is important to note, that
  91. whenever  an  envelope  is  copied,  only  the pointer to the namestring is
  92. copied.   Therefore it must be guaranteed that the name is valid as long as
  93. the envelope live.
  94.  
  95. The e_copyfunc field must eighter be NULL or point to a C function with the
  96. following declaration:
  97.  
  98.  
  99.    Envelope *my_copyfunc(source,target)
  100.    Envelope *source,*target;
  101.    {  ....
  102.       return target;
  103.    }
  104.  
  105.  
  106.    It  is  important, that 'target' is returned, as this pointer is used to
  107. handle  the  copy  afterwards.  Copy-functions should be made fast, because
  108. e-space  is  locked  while copying, preventing other tasks from altering e-
  109. space  in  the  meantime.  It is always the e_copyfunc of the source in any
  110. given operation, that is significant.
  111.  
  112.    The  e_proc field is used only by Eval().  When Eval() is called it must
  113. point to a C function with the following declaration:
  114.  
  115.  
  116.    Envelope *new_process(passed_env)
  117.    Envelope *passed_env;
  118.    { ... 
  119.       return passed_env;
  120.    }
  121.  
  122. ---------------------------------------------------------------------------
  123.                              Function summary
  124.                              -----------------
  125. ---------------------------------------------------------------------------
  126.  
  127. Envelope *InitEnvelope(env,name,len,copyfunc)
  128.    D0                   A1  A0   D0   A2
  129. Envelope *env;
  130. char     *name;
  131. ULONG    len;
  132. Envelope *(*copyfunc)();
  133.  
  134.    Initializes  env  with  the  name 'name', length of envelope+contents in
  135.    bytes:  'len', and sets the copyfunc for the envelope to copyfunc.  The
  136.    Eval()  function  (e_proc)  is  not touched.  InitEnvelope() returns the
  137.    newly  initialized  envelope.   Use the macro NoCopyFunc to specify that
  138.    the e_copyfunc should be initialized to NULL.
  139.  
  140.    SEE ALSO
  141.       CreateEnvelope(), Rd().
  142.  
  143. ---------------------------------------------------------------------------
  144.  
  145. Envelope *In(env)
  146.    D0         A1
  147. Envelope *env;
  148.  
  149.    Tries  to  extract an envelope from e-space with a matching name.  If no
  150.    envelopes  in  e-space  matches,  the  caller  is  put  to sleep until a
  151.    matching  envelope  is  entered  into e-space.  The matching envelope is
  152.    taken out of e-space and returned.  No copying is done.
  153.  
  154.    SEE ALSO
  155.       Rd(), Inp(), AwaitNamedEnvelope().
  156.  
  157. ---------------------------------------------------------------------------
  158.  
  159. Envelope *Rd(env)
  160.    D0         A1
  161. Envelope *env;
  162.  
  163.    Works  like  In(),  but  copies  the  envelope  from e-space to env.  If
  164.    e_copyfunc of the envelope to be extracted is non-NULL, that function is
  165.    used  to  copy  envelope and contents.  If copyfunc is NULL the envelope
  166.    and  contents  just  after  it  are copied byte for byte to the location
  167.    given  by  env.   No  envelope  is  taken  out of e-space.
  168.    The copyfunc feature allows complex structures to be copied (eg.  binary
  169.    trees).   The  declaration of a copyfunc is covered under "The Envelope"
  170.    above.  Rd() returns a pointer to the copy.
  171.  
  172.    SEE ALSO
  173.       In(), Rdp().
  174.  
  175. ---------------------------------------------------------------------------
  176.  
  177. void Out(env)
  178.          A1
  179. Envelope *env;
  180.  
  181.    Puts  env  into  e-space.   This  is  a  non-copying operation, so it is
  182.    possible,  although  NOT  recommended,  to  alter  the  contents  of the
  183.    envelope while it is in e-space.
  184.  
  185.    SEE ALSO
  186.       CopyOut(), OutEmptyEnvelope().
  187.  
  188. ---------------------------------------------------------------------------
  189.  
  190. BOOL CopyOut(env)
  191.  D0           A1
  192. Envelope *env;
  193.  
  194.    Puts a copy of env into e-space.  If env->e_copyfunc is non-NULL this is
  195.    used  to  copy  the envelope and contents to a newly created envelope of
  196.    the  same  size  as 'env'.  If e_copyfunc is NULL the envelope is copied
  197.    byte for byte.
  198.  
  199.    Use  this  to put multiple copies of an envelope into e-space.  If there
  200.    is  not  enough  memory  to CreateEnvelope() the new envelope, CopyOut()
  201.    returns FALSE.  If all goes well TRUE is returned.
  202.  
  203.    SEE ALSO
  204.       Rd(), Out(), OutEmptyEnvelope().
  205.  
  206. ---------------------------------------------------------------------------
  207.  
  208. struct Task *Eval(env,pri,stacksize,et)
  209.         D0         A1  D0    D1     D2
  210. Envelope *env;
  211. long pri,et;
  212. ULONG stacksize;
  213.  
  214.    Eval() creates a new Process or Task (by StartProcess() or StartTask()),
  215.    determined  by  the 'et' parameter.  If this parameter is EVAL_PROCESS a
  216.    process  is  started,  and if it is EVAL_TASK a task is started.  Eval()
  217.    passes  the  envelope 'env' to the new process/task without any copying.
  218.    The  body  of the process is the C-function in env->e_proc.  This should
  219.    have the following declaration:
  220.  
  221.    Envelope *new_process(passed_env)
  222.    Envelope *passed_env;
  223.    { ... }
  224.  
  225.    The  stacksize  of the new process/task is set to 'stacksize' bytes, and
  226.    the  process/task  gets the priority 'pri'.  The name of the new process
  227.    becomes the name of the passed envelope.
  228.  
  229.    When  the  body-function  returns an envelope, this envelope is put into
  230.    e-space  with an Out()-call just before the task/process dies.  This can
  231.    be used for syncronization between tasks.  Be warned though!  The system
  232.    will panic if the function does in fact NOT return an envelope.  If NULL
  233.    is  returned  from  the  body-function,  the process/task just dies, and
  234.    nothing is added to e-space.
  235.  
  236.    Eval()  carries all registers over to the new task/process except A7 and
  237.    A2!.
  238.  
  239.    Eval()  returns a pointer to the Task structure of the new process/task,
  240.    or NULL if something goes wrong.
  241.  
  242.    SEE ALSO
  243.       CreateProcess(), Out(), CreateTask().
  244.  
  245. ---------------------------------------------------------------------------
  246.  
  247. Envelope *Inp(env)
  248.    D0          A1
  249. Envelope *env;
  250.  
  251.    Inp()  tests  if  a matching envelope exists in e-space, and if so takes
  252.    that  envelope  out  of e-space and returns it.  If no matching envelope
  253.    exists in e-space, NULL is returned immediately.
  254.  
  255.    SEE ALSO
  256.       In(), Rdp(), PollNamedEnvelope().
  257.  
  258. ---------------------------------------------------------------------------
  259.  
  260. Envelope *Rdp(env)
  261.    D0         A1
  262. Envelope *env;
  263.  
  264.    Tests  if  a  matching envelope exists in e-space, and if so copies that
  265.    envelope  to  env.   If  no matching envelope exists in e-space, NULL is
  266.    returned immediately.
  267.  
  268.    SEE ALSO
  269.       Inp(), Rd().
  270.  
  271. ---------------------------------------------------------------------------
  272.  
  273. struct Task *StartTask(proc,name,pri,stacksize)
  274.      D0                 A0   A1   D0   D1
  275. void (*proc)();
  276. char *name;
  277. long pri;
  278. ULONG stacksize;  /* stack size in bytes, must be even */
  279.  
  280.    This  allocates  a stack, and a Task structure, and starts a new task to
  281.    execute proc.  All registers except the stackpointer are carried over to
  282.    the  new  task.   This  is  necessary since many compilers use register-
  283.    relative  addressing  to  access  global  variables.  When the procedure
  284.    returns,  the  task  dies.
  285.    The  task-structure  and  the  stack  are  freed  automagically when the
  286.    process  terminates by returning or calling RemTask(NULL).  A pointer to
  287.    the newly created Task is returned, or NULL if something goes wrong.
  288.  
  289.    SEE ALSO
  290.       StartProcess(), Eval().
  291.  
  292. ---------------------------------------------------------------------------
  293.  
  294. struct Process *StartProcess(proc,name,pri,stacksize)
  295.           D0                  A0   A1  D0     D1
  296. void (*proc)();
  297. char *name;
  298. long pri;
  299. ULONG stacksize;  /* size is in bytes */
  300.  
  301.    Same as StartTask(), just creates a Process instead.  Proc does not have
  302.    to  be  at  the  start  of  a  segment or lie on a 4-byte boundary.  The
  303.    process  structure  and  stack  are automatically freed when the process
  304.    dies by returning or calling Exit().  The code is NOT unloaded.
  305.  
  306.    StartProcess()  returns a pointer to the real Process-struct ie. not the
  307.    messageport in it.
  308.  
  309.    SEE ALSO
  310.       StartTask(), Eval().
  311.  
  312. ---------------------------------------------------------------------------
  313.  
  314. Envelope *AwaitNamedEnvelope(name)
  315.   D0                          A0
  316. char *name;
  317.  
  318.    AwaitNamedEnvelope  creates  a  temporary envelope with the name 'name',
  319.    and  waits  for a matching envelope to appear in e-space.  When and if a
  320.    matching envelope appears, it is taken out of e-space and returned.  The
  321.    temporary  envelope  is  disposed  of.   Use  this  instead of In() when
  322.    appropriate.
  323.  
  324.    SEE ALSO
  325.       In().
  326.  
  327. ---------------------------------------------------------------------------
  328.  
  329. Envelope *PollNamedEnvelope(name)
  330.   D0                         A0
  331. char *name;
  332.  
  333.    PollNamedEnvelope()  checks if an envelope with the given name exists in
  334.    e-space,  and  if  so, it takes it out of e-space and returns it.  If no
  335.    envelope  with  the  given  name  exists  in  e-space  NULL  is returned
  336.    immediately.   This  is  actually  a  combination  of InitEnvelope() and
  337.    Inp().
  338.  
  339.    SEE ALSO
  340.       Inp().
  341.  
  342. ---------------------------------------------------------------------------
  343.  
  344. BOOL OutEmptyEnvelope(name)
  345.                        A0
  346. char *name;
  347.  
  348.    OutEmptyEnvelope()  creates  an  empty  envelope, with CreateEnvelope(),
  349.    gives  it  the  name  'name'  and puts it into e-space with Out().  This
  350.    could  be  used  for simple synchronization.
  351.  
  352.    OutEmptyEnvelope() returns FALSE if there is too little memory to create
  353.    an empty envelope.  Otherwise TRUE is returned.
  354.  
  355.    SEE ALSO
  356.       Out().
  357.  
  358. ---------------------------------------------------------------------------
  359.  
  360. Envelope *CreateEnvelope(name,size)
  361.    D0                     A0   D0
  362. char *name;
  363. ULONG size;
  364.  
  365.    CreateEnvelope()  creates  a new envelope using AllocMem().  Size is the
  366.    byte-size  of  the  envelope+contents.   The new envelope is initialized
  367.    with  InitEnvelope()  to have the given length, and no copyfunc or proc.
  368.    If there is not enough memory for the creation, NULL is returned.
  369.  
  370.    EXAMPLE
  371.       struct FilledEnv {
  372.          Envelope env;
  373.          struct Image img;
  374.       };
  375.       struct FilledEnv *fe;
  376.       ....
  377.       fe = (struct FilledEnv *)CreateEnvelope("imageenvelope",
  378.                                           (ULONG)sizeof(struct FilledEnv));
  379.  
  380.  
  381.    SEE ALSO
  382.       DisposeEnvelope(), InitEnvelope().
  383.  
  384. ---------------------------------------------------------------------------
  385.  
  386. void DisposeEnvelope(env)
  387.                       A1
  388. Envelope *env;
  389.  
  390.    DisposeEnvelope()  frees  the  space  taken up by the envelope, by using
  391.    FreeMem().  If NULL is passed to this routine nothing is done.
  392.  
  393.    EXAMPLE
  394.       ....
  395.       do { DisposeEnvelope(p = PollNamedEnvelope(name)) } while(p);
  396.       ....
  397.  
  398.    SEE ALSO
  399.       CreateEnvelope().
  400.  
  401. ---------------------------------------------------------------------------
  402.  
  403. Envelope *TimedIn(env,secs,micros)
  404.    D0              A1  D0    D1
  405. Envelope *env;
  406. ULONG secs,micros;
  407.  
  408.    TimedIn()  works  like  In()  but  waits  at most for 'secs' seconds and
  409.    'micros'  microseconds  with  the  help of timer.device.  If an envelope
  410.    with  a  matching  name  already exists in e-space TimedIn() will return
  411.    immediately,  and if no envelope appears in e-space before the time runs
  412.    out NULL is returned.  If timer.device can't be opened or something else
  413.    goes wrong, -1 is returned immediately.
  414.  
  415.    The seconds and microseconds must be normalized to satisfy timer.device,
  416.    ie.  'micros' must be less than 1000000.
  417.  
  418.    The  UNIT_VBLANK  of  the timer.device is used, so the resolution of the
  419.    timeout  is  less  then  1/50  secs  (for PAL systems) or 1/60 (for NTSC
  420.    systems).
  421.  
  422.    EXAMPLE
  423.       ...
  424.       /* wait at most 10 seconds for 'test' */
  425.       e1 = TimedIn(CreateEnvelope("test",e_sizeof,10L,0L);
  426.       ...
  427.  
  428.    SEE ALSO
  429.       TimedRd(), AwaitTimed(), In().
  430.  
  431. ---------------------------------------------------------------------------
  432.  
  433. Envelope *TimedRd(env,secs,micros)
  434.   D0               A1  D0     D1
  435. Envelope *env;
  436. ULONG secs,micros;
  437.  
  438.    TimedRd()  works  like  TimedIn() but does a Rd() operation if or when a
  439.    matching envelope turns up in e-space.
  440.  
  441.    SEE ALSO
  442.       TimedIn(), Rd().
  443.  
  444. ---------------------------------------------------------------------------
  445.  
  446. void AsyncIn(env,port)
  447.               A1  A0
  448. Envelope *env;
  449. struct MsgPort *port;
  450.  
  451.    AsyncIn()  requests a matching envelope in e-space like In() but returns
  452.    immediately  in  all  cases.  When and if a matching envelope appears in
  453.    e-space, the envelope is removed from e-space and posted to the message-
  454.    port 'port' contained in an EnvMsg.
  455.  
  456.    It  is  possible  to  have  many  requests for the same envelope hanging
  457.    around  at  once.  When a matching envelope appears in e-space the first
  458.    posted request is satisfied first.
  459.  
  460.    AsyncIn()  may  give a recoverable alert #00010000 (no memory) if memory
  461.    is  too short to allocate an intermediary WaitStruct structure.  You may
  462.    also  get  this  alert  if memory runs short when an Out() call tries to
  463.    create an EnvMsg to post to 'port'.
  464.  
  465.    EXAMPLE
  466.       ...
  467.       struct EnvMsg *msg;
  468.       Envelope *env, *env2;
  469.       ...
  470.       env = CreateEnvelope("bla",e_sizeof);
  471.       AsyncIn(env,MyPort);
  472.       ...
  473.       WaitPort(MyPort);
  474.       msg = GetMsg(MyPort);
  475.       env2 = msg->em_env;
  476.       ...
  477.  
  478.    SEE ALSO
  479.       AsyncRd(), In(), AsyncRequest().
  480.  
  481. ---------------------------------------------------------------------------
  482.  
  483. void AsyncRd(env,port)
  484.               A1  A0
  485. Envelope *env;
  486. struct MsgPort *port;
  487.  
  488.    AsyncRd()  works like AsyncIn() but doesn't remove the matching envelope
  489.    from  e-space.   Instead  a  copy  is made to the passed envelope 'env',
  490.    which  is  subsequently  embedded  in  the  EnvMsg message passed to the
  491.    messageport 'port'.
  492.  
  493.    SEE ALSO
  494.       AsyncIn(), Rd().
  495.  
  496. ---------------------------------------------------------------------------
  497.  
  498. Envelope *AwaitTimed(name,secs,micros)
  499.   D0                  A0   D0   D1
  500. char *name;
  501. ULONG secs,micros;
  502.  
  503.    AwaitTimed()  is a combination of CreateEnvelope() and TimedIn().  Works
  504.    like TimedIn() except that you supply the name of the requested envelope
  505.    instead of a full-featured envelope.
  506.    
  507.    SEE ALSO
  508.       TimedIn(), TimedRd(), In(), AwaitNamedEnvelope().
  509.  
  510. ---------------------------------------------------------------------------
  511.  
  512. void AsyncRequest(name,port)
  513.                    A0   D0
  514. char *name;
  515. struct MsgPort *port;
  516.  
  517.    AsyncRequest()  is  a  combination  of  CreateEnvelope()  and AsyncIn().
  518.    Works  like  AsyncIn()  except  that  you  supply the name of the wanted
  519.    envelope instead of a full-featured envelope.  AsyncRequest() can give a
  520.    recoverable alert #00010000 (Out of memory) if there's not enough memory
  521.    for CreateEnvelope() to allocate.
  522.  
  523.    SEE ALSO
  524.       CreateEnvelope(), AsyncIn(), In(), AwaitNamedEnvelope().
  525.  
  526. ---------------------------------------------------------------------------
  527.  
  528. char *UniqueName(buffer)
  529.   D0               A0
  530. char *buffer;
  531.  
  532.    UniqueName() generates a suffix to the null-terminated string pointed to
  533.    by  'buffer'.  The buffer must be large enough to acommodate 8 bytes for
  534.    the  suffix  including  the  terminating  null.   The suffix consists of
  535.    printable  characters  only, so you can (eg.  for debugging) write it to
  536.    the  screen,  with a normal printf().  The suffix will not repeat before
  537.    more that 3.5E+12 iterations.
  538.  
  539.    UniqueName() returns the passed pointer.
  540.  
  541.    SEE ALSO
  542.       CreateEnvelope(), InitEnvelope().
  543.  
  544.