home *** CD-ROM | disk | FTP | other *** search
- odin.doc, version 2.7, 9-Sep-90, Release 2
- Created 3-Jul-90 by Peter Ørbæk (C)
-
- Documentation for odin.library
- ------------------------------
-
- The main intention of this library is to provide an easier way to
- accomplish Inter-Process Communications (IPC) on the Amiga using C or
- assembler. Most of the functions provided are inspired by Linda, an add-on
- language for C and other high-level languages, which provides a simple, yet
- poverful way to do IPC.
-
- Instead of implementing the Linda language directly, I have chosen a
- more pragmatic approach to provide much of the same functionallity, but
- without all of the theoretic elegance in Linda.
-
-
- Envelopes and e-space
- ---------------------
-
- The central concept in odin.library is the envelope. An envelope is
- used to pass information between processes, and they are used to hold
- information residing in e-space. In C an envelope is a structure that
- begins with the Envelope-structure defined in odin.h. This structure is
- explained below.
-
- There's no restrictions on the contents of an envelope, the contents
- being whatever comes after the Envelope-structure. The contents need not
- be contigous in memory. You can specify a C-function to serve as a
- copying-routine for each envelope.
-
- The e-space is an abstact storage containing envelopes and their
- contents. Envelopes are identified by a name, ie. a null-terminated ASCII
- string. Envelopes can be put into and retrieved from e-space via the name.
- E-space can contain many envelopes with the same name. Envelopes with the
- same name will be retrieved in the same order as they have been inserted
- into e-space, forming a queue.
-
- To prevent two different programs from unintentional interference with
- each others envelopes a naming convention should be applied. My suggestion
- is to name envelopes intended for private use within some internal task
- like this: "<ProgramName>:<envelopename>" (this is not used in my
- examples...).
-
- Function overview
- -----------------
-
- You can generate 'unique' envelope-names with the function UniqueName().
-
- Functions for general envelope-management are: CreateEnvelope(),
- InitEnvelope() and DisposeEnvelope(). To put envelopes into e-space use:
- Out(),CopyOut() or OutEmptyEnvelope(). You can wait for an envelope to
- appear in e-space with: In(), Rd() and AwaitNamedEnvelope(). You can also
- poll for the existence of envelopes in e-space with: Inp(), Rdp() and
- PollNamedEnvelope().
-
- You can wait for an envelope to appear in e-space within a given time
- with: TimedIn(), TimedRd() and AwaitTimed(), and you can request that your
- task gets a message when an envelope with a given name appears in e-space
- with: AsyncIn(), AsyncRd() and AsyncRequest().
-
- New tasks and processes can be launched by the Eval() function. Eval()
- provides a simple, yet powerful way to transfer arguments to the new task/
- process, and a way to determine when the new task/process is finished.
-
- There are also two lower-level functions for creating tasks/processes:
- StartTask() and StartProcess().
-
- System requirements to use odin.library is a mere 10K of free memory and
- KickStart 33.180 (V1.2) or later.
-
- The envelope
- ------------
-
- The C structure for an envelope, defined in include/odin.h is as
- follows:
-
-
- typedef struct _Env {
- struct MinNode e_link; /* first a link for use in e-space */
- STRPTR e_name; /* the name of this envelope */
- ULONG e_len; /* bytelength of whole envelope */
- struct _Env * (*e_copyfunc)();/* opt. C-function for copying */
- struct _Env * (*e_proc)(); /* C-func. to call in Eval() */
- } Envelope;
-
-
- The e_link field is of no interest for casual users, and is used
- internally to keep track of the envelopes while they float in e-space. The
- e_name field points to the namestring. It is important to note, that
- whenever an envelope is copied, only the pointer to the namestring is
- copied. Therefore it must be guaranteed that the name is valid as long as
- the envelope live.
-
- The e_copyfunc field must eighter be NULL or point to a C function with the
- following declaration:
-
-
- Envelope *my_copyfunc(source,target)
- Envelope *source,*target;
- { ....
- return target;
- }
-
-
- It is important, that 'target' is returned, as this pointer is used to
- handle the copy afterwards. Copy-functions should be made fast, because
- e-space is locked while copying, preventing other tasks from altering e-
- space in the meantime. It is always the e_copyfunc of the source in any
- given operation, that is significant.
-
- The e_proc field is used only by Eval(). When Eval() is called it must
- point to a C function with the following declaration:
-
-
- Envelope *new_process(passed_env)
- Envelope *passed_env;
- { ...
- return passed_env;
- }
-
- ---------------------------------------------------------------------------
- Function summary
- -----------------
- ---------------------------------------------------------------------------
-
- Envelope *InitEnvelope(env,name,len,copyfunc)
- D0 A1 A0 D0 A2
- Envelope *env;
- char *name;
- ULONG len;
- Envelope *(*copyfunc)();
-
- Initializes env with the name 'name', length of envelope+contents in
- bytes: 'len', and sets the copyfunc for the envelope to copyfunc. The
- Eval() function (e_proc) is not touched. InitEnvelope() returns the
- newly initialized envelope. Use the macro NoCopyFunc to specify that
- the e_copyfunc should be initialized to NULL.
-
- SEE ALSO
- CreateEnvelope(), Rd().
-
- ---------------------------------------------------------------------------
-
- Envelope *In(env)
- D0 A1
- Envelope *env;
-
- Tries to extract an envelope from e-space with a matching name. If no
- envelopes in e-space matches, the caller is put to sleep until a
- matching envelope is entered into e-space. The matching envelope is
- taken out of e-space and returned. No copying is done.
-
- SEE ALSO
- Rd(), Inp(), AwaitNamedEnvelope().
-
- ---------------------------------------------------------------------------
-
- Envelope *Rd(env)
- D0 A1
- Envelope *env;
-
- Works like In(), but copies the envelope from e-space to env. If
- e_copyfunc of the envelope to be extracted is non-NULL, that function is
- used to copy envelope and contents. If copyfunc is NULL the envelope
- and contents just after it are copied byte for byte to the location
- given by env. No envelope is taken out of e-space.
- The copyfunc feature allows complex structures to be copied (eg. binary
- trees). The declaration of a copyfunc is covered under "The Envelope"
- above. Rd() returns a pointer to the copy.
-
- SEE ALSO
- In(), Rdp().
-
- ---------------------------------------------------------------------------
-
- void Out(env)
- A1
- Envelope *env;
-
- Puts env into e-space. This is a non-copying operation, so it is
- possible, although NOT recommended, to alter the contents of the
- envelope while it is in e-space.
-
- SEE ALSO
- CopyOut(), OutEmptyEnvelope().
-
- ---------------------------------------------------------------------------
-
- BOOL CopyOut(env)
- D0 A1
- Envelope *env;
-
- Puts a copy of env into e-space. If env->e_copyfunc is non-NULL this is
- used to copy the envelope and contents to a newly created envelope of
- the same size as 'env'. If e_copyfunc is NULL the envelope is copied
- byte for byte.
-
- Use this to put multiple copies of an envelope into e-space. If there
- is not enough memory to CreateEnvelope() the new envelope, CopyOut()
- returns FALSE. If all goes well TRUE is returned.
-
- SEE ALSO
- Rd(), Out(), OutEmptyEnvelope().
-
- ---------------------------------------------------------------------------
-
- struct Task *Eval(env,pri,stacksize,et)
- D0 A1 D0 D1 D2
- Envelope *env;
- long pri,et;
- ULONG stacksize;
-
- Eval() creates a new Process or Task (by StartProcess() or StartTask()),
- determined by the 'et' parameter. If this parameter is EVAL_PROCESS a
- process is started, and if it is EVAL_TASK a task is started. Eval()
- passes the envelope 'env' to the new process/task without any copying.
- The body of the process is the C-function in env->e_proc. This should
- have the following declaration:
-
- Envelope *new_process(passed_env)
- Envelope *passed_env;
- { ... }
-
- The stacksize of the new process/task is set to 'stacksize' bytes, and
- the process/task gets the priority 'pri'. The name of the new process
- becomes the name of the passed envelope.
-
- When the body-function returns an envelope, this envelope is put into
- e-space with an Out()-call just before the task/process dies. This can
- be used for syncronization between tasks. Be warned though! The system
- will panic if the function does in fact NOT return an envelope. If NULL
- is returned from the body-function, the process/task just dies, and
- nothing is added to e-space.
-
- Eval() carries all registers over to the new task/process except A7 and
- A2!.
-
- Eval() returns a pointer to the Task structure of the new process/task,
- or NULL if something goes wrong.
-
- SEE ALSO
- CreateProcess(), Out(), CreateTask().
-
- ---------------------------------------------------------------------------
-
- Envelope *Inp(env)
- D0 A1
- Envelope *env;
-
- Inp() tests if a matching envelope exists in e-space, and if so takes
- that envelope out of e-space and returns it. If no matching envelope
- exists in e-space, NULL is returned immediately.
-
- SEE ALSO
- In(), Rdp(), PollNamedEnvelope().
-
- ---------------------------------------------------------------------------
-
- Envelope *Rdp(env)
- D0 A1
- Envelope *env;
-
- Tests if a matching envelope exists in e-space, and if so copies that
- envelope to env. If no matching envelope exists in e-space, NULL is
- returned immediately.
-
- SEE ALSO
- Inp(), Rd().
-
- ---------------------------------------------------------------------------
-
- struct Task *StartTask(proc,name,pri,stacksize)
- D0 A0 A1 D0 D1
- void (*proc)();
- char *name;
- long pri;
- ULONG stacksize; /* stack size in bytes, must be even */
-
- This allocates a stack, and a Task structure, and starts a new task to
- execute proc. All registers except the stackpointer are carried over to
- the new task. This is necessary since many compilers use register-
- relative addressing to access global variables. When the procedure
- returns, the task dies.
- The task-structure and the stack are freed automagically when the
- process terminates by returning or calling RemTask(NULL). A pointer to
- the newly created Task is returned, or NULL if something goes wrong.
-
- SEE ALSO
- StartProcess(), Eval().
-
- ---------------------------------------------------------------------------
-
- struct Process *StartProcess(proc,name,pri,stacksize)
- D0 A0 A1 D0 D1
- void (*proc)();
- char *name;
- long pri;
- ULONG stacksize; /* size is in bytes */
-
- Same as StartTask(), just creates a Process instead. Proc does not have
- to be at the start of a segment or lie on a 4-byte boundary. The
- process structure and stack are automatically freed when the process
- dies by returning or calling Exit(). The code is NOT unloaded.
-
- StartProcess() returns a pointer to the real Process-struct ie. not the
- messageport in it.
-
- SEE ALSO
- StartTask(), Eval().
-
- ---------------------------------------------------------------------------
-
- Envelope *AwaitNamedEnvelope(name)
- D0 A0
- char *name;
-
- AwaitNamedEnvelope creates a temporary envelope with the name 'name',
- and waits for a matching envelope to appear in e-space. When and if a
- matching envelope appears, it is taken out of e-space and returned. The
- temporary envelope is disposed of. Use this instead of In() when
- appropriate.
-
- SEE ALSO
- In().
-
- ---------------------------------------------------------------------------
-
- Envelope *PollNamedEnvelope(name)
- D0 A0
- char *name;
-
- PollNamedEnvelope() checks if an envelope with the given name exists in
- e-space, and if so, it takes it out of e-space and returns it. If no
- envelope with the given name exists in e-space NULL is returned
- immediately. This is actually a combination of InitEnvelope() and
- Inp().
-
- SEE ALSO
- Inp().
-
- ---------------------------------------------------------------------------
-
- BOOL OutEmptyEnvelope(name)
- A0
- char *name;
-
- OutEmptyEnvelope() creates an empty envelope, with CreateEnvelope(),
- gives it the name 'name' and puts it into e-space with Out(). This
- could be used for simple synchronization.
-
- OutEmptyEnvelope() returns FALSE if there is too little memory to create
- an empty envelope. Otherwise TRUE is returned.
-
- SEE ALSO
- Out().
-
- ---------------------------------------------------------------------------
-
- Envelope *CreateEnvelope(name,size)
- D0 A0 D0
- char *name;
- ULONG size;
-
- CreateEnvelope() creates a new envelope using AllocMem(). Size is the
- byte-size of the envelope+contents. The new envelope is initialized
- with InitEnvelope() to have the given length, and no copyfunc or proc.
- If there is not enough memory for the creation, NULL is returned.
-
- EXAMPLE
- struct FilledEnv {
- Envelope env;
- struct Image img;
- };
- struct FilledEnv *fe;
- ....
- fe = (struct FilledEnv *)CreateEnvelope("imageenvelope",
- (ULONG)sizeof(struct FilledEnv));
-
-
- SEE ALSO
- DisposeEnvelope(), InitEnvelope().
-
- ---------------------------------------------------------------------------
-
- void DisposeEnvelope(env)
- A1
- Envelope *env;
-
- DisposeEnvelope() frees the space taken up by the envelope, by using
- FreeMem(). If NULL is passed to this routine nothing is done.
-
- EXAMPLE
- ....
- do { DisposeEnvelope(p = PollNamedEnvelope(name)) } while(p);
- ....
-
- SEE ALSO
- CreateEnvelope().
-
- ---------------------------------------------------------------------------
-
- Envelope *TimedIn(env,secs,micros)
- D0 A1 D0 D1
- Envelope *env;
- ULONG secs,micros;
-
- TimedIn() works like In() but waits at most for 'secs' seconds and
- 'micros' microseconds with the help of timer.device. If an envelope
- with a matching name already exists in e-space TimedIn() will return
- immediately, and if no envelope appears in e-space before the time runs
- out NULL is returned. If timer.device can't be opened or something else
- goes wrong, -1 is returned immediately.
-
- The seconds and microseconds must be normalized to satisfy timer.device,
- ie. 'micros' must be less than 1000000.
-
- The UNIT_VBLANK of the timer.device is used, so the resolution of the
- timeout is less then 1/50 secs (for PAL systems) or 1/60 (for NTSC
- systems).
-
- EXAMPLE
- ...
- /* wait at most 10 seconds for 'test' */
- e1 = TimedIn(CreateEnvelope("test",e_sizeof,10L,0L);
- ...
-
- SEE ALSO
- TimedRd(), AwaitTimed(), In().
-
- ---------------------------------------------------------------------------
-
- Envelope *TimedRd(env,secs,micros)
- D0 A1 D0 D1
- Envelope *env;
- ULONG secs,micros;
-
- TimedRd() works like TimedIn() but does a Rd() operation if or when a
- matching envelope turns up in e-space.
-
- SEE ALSO
- TimedIn(), Rd().
-
- ---------------------------------------------------------------------------
-
- void AsyncIn(env,port)
- A1 A0
- Envelope *env;
- struct MsgPort *port;
-
- AsyncIn() requests a matching envelope in e-space like In() but returns
- immediately in all cases. When and if a matching envelope appears in
- e-space, the envelope is removed from e-space and posted to the message-
- port 'port' contained in an EnvMsg.
-
- It is possible to have many requests for the same envelope hanging
- around at once. When a matching envelope appears in e-space the first
- posted request is satisfied first.
-
- AsyncIn() may give a recoverable alert #00010000 (no memory) if memory
- is too short to allocate an intermediary WaitStruct structure. You may
- also get this alert if memory runs short when an Out() call tries to
- create an EnvMsg to post to 'port'.
-
- EXAMPLE
- ...
- struct EnvMsg *msg;
- Envelope *env, *env2;
- ...
- env = CreateEnvelope("bla",e_sizeof);
- AsyncIn(env,MyPort);
- ...
- WaitPort(MyPort);
- msg = GetMsg(MyPort);
- env2 = msg->em_env;
- ...
-
- SEE ALSO
- AsyncRd(), In(), AsyncRequest().
-
- ---------------------------------------------------------------------------
-
- void AsyncRd(env,port)
- A1 A0
- Envelope *env;
- struct MsgPort *port;
-
- AsyncRd() works like AsyncIn() but doesn't remove the matching envelope
- from e-space. Instead a copy is made to the passed envelope 'env',
- which is subsequently embedded in the EnvMsg message passed to the
- messageport 'port'.
-
- SEE ALSO
- AsyncIn(), Rd().
-
- ---------------------------------------------------------------------------
-
- Envelope *AwaitTimed(name,secs,micros)
- D0 A0 D0 D1
- char *name;
- ULONG secs,micros;
-
- AwaitTimed() is a combination of CreateEnvelope() and TimedIn(). Works
- like TimedIn() except that you supply the name of the requested envelope
- instead of a full-featured envelope.
-
- SEE ALSO
- TimedIn(), TimedRd(), In(), AwaitNamedEnvelope().
-
- ---------------------------------------------------------------------------
-
- void AsyncRequest(name,port)
- A0 D0
- char *name;
- struct MsgPort *port;
-
- AsyncRequest() is a combination of CreateEnvelope() and AsyncIn().
- Works like AsyncIn() except that you supply the name of the wanted
- envelope instead of a full-featured envelope. AsyncRequest() can give a
- recoverable alert #00010000 (Out of memory) if there's not enough memory
- for CreateEnvelope() to allocate.
-
- SEE ALSO
- CreateEnvelope(), AsyncIn(), In(), AwaitNamedEnvelope().
-
- ---------------------------------------------------------------------------
-
- char *UniqueName(buffer)
- D0 A0
- char *buffer;
-
- UniqueName() generates a suffix to the null-terminated string pointed to
- by 'buffer'. The buffer must be large enough to acommodate 8 bytes for
- the suffix including the terminating null. The suffix consists of
- printable characters only, so you can (eg. for debugging) write it to
- the screen, with a normal printf(). The suffix will not repeat before
- more that 3.5E+12 iterations.
-
- UniqueName() returns the passed pointer.
-
- SEE ALSO
- CreateEnvelope(), InitEnvelope().
-
-