asyncio.doc

     --background-- 
     --history--() 
     --changes--() 
     CloseAsync() 
     FGetsAsync() 
     FGetsLenAsync() 
     OpenAsync() 
     ReadAsync() 
     ReadCharAsync() 
     ReadLineAsync() 
     SeekAsync() 
     WriteAsync() 
     WriteCharAsync() 
     WriteLineAsync() 


asyncio/--background--


This documentation and source code was written by Martin Taillefer.

Reading and writing data is crucial to most applications and is in many cases
a major bottleneck. Using AmigaDOS' sophisticated file system architecture
can help reduce, and sometimes eliminate, the time spent waiting for IO to
complete. This package offers a few small routines that can greatly improve
an application's IO performance.

Normally, an application processes a file in a manner similar to the following:

  1 - Open the file

  2 - Read some data

  3 - Process data just read

  4 - Repeat steps 2 and 3 until all data is processed

  5 - Close file

Although the above sequence works fine, it doesn't make full use of the Amiga's
multitasking abilities. Step 2 in the above can become a serious bottleneck.
Whenever the application needs some data by using the DOS Read() function,
AmigaDOS has to put that task to sleep, and initiate a request to the file
system to have it fetch the data. The file system then starts up the disk
hardware and reads the data. Once the data is read, the application is woken up
and can start processing the data just read.

The point to note in the above paragraph is that when the file system is
reading data from disk, the application is asleep. Wouldn't it be nice if the
application could keep running while data is being fetched for it?

Most Amiga hard drives make use of DMA (Direct Memory Access). DMA enables a
hard drive to transfer data to memory _at the same time_ as the CPU does some
work. This parallelism is what makes the set of accompanying routines so
efficient. They exploit the fact that data can be transfered to memory while
the application is busy processing other data.

Using the asynchronous IO routines, an application's IO happens like this:

  1 - Open the file, ask the file system to start reading ahead

  2 - Read some data, ask the file system to read more data

  3 - Process data

  4 - Repeat steps 2 and 3 until all data is processed

  5 - Close file

Immediately after opening the file, a request is sent to the file system to get
it reading data in the background. By the time the application gets around to
reading the first byte of data, it is likely already in memory. That means the
application doesn't need to wait and can start processing the data. As soon as
the application starts processing data from the file, a second request is sent
out to the file system to fill up a second buffer. Once the application is done
processing the first buffer, it starts processing the second one. When this
happens, the file system starts filling up the first buffer again with new
data. This process continues until all data has been read.

The whole technique is known as "double-buffered asynchronous IO" since it uses
two buffers, and happens in the background (asynchronously).

The set of functions presented below offers high-performance IO using the
technique described above. The interface is very similar to standard AmigaDOS
files. These routines enable full asynchronous read/write of any file.


asyncio/--history--


23-Mar-94
---------

  - When seeking within the current read buffer, the wrong packet would be
    sent out to be filled asynchronously. Depending on the data read from
    the buffer, and how fast it was read, you could end up getting incorrect
    data on subsequent ReadAsync() calls.

  - There was actually bufferSize*2 bytes allocated for IO buffers instead
    of just bufferSize. This is fixed. So if you want the same effective
    buffer size as before, you must double the value of the bufferSize
    argument supplied to OpenAsync().

  - MEMF_PUBLIC is now specified for the IO buffers. This is in support
    of VM hacks such as GigaMem.

  - A Seek() call had the mode and offset parameters reversed. The code worked,
    because both values were luckily always 0, but it was not very clean.

  - Now uses a typedef for the AsyncFile structure, and enums for the
    open modes and seek modes.

16-Feb-94
---------

  - SeekAsync() now consistently works. It was getting confused when called
    multiple times in a row with no intervening IO.

  - WriteAsync() would produce garbage in the destination file if it had
    to bring up a "Disk is full" requester, and the user freed some room on
    the disk and selected "Retry".


asyncio/--changes--


All changes described in this section were made by Magnus Holmgren. If you
want to contact me about something, feel free to send a message to
cmh@lls.se or "Magnus Holmgren", 2:203/512.10@fidonet.org.

I've been in contact with Martin Taillefer, and he is aware of me releasing
new versions of (t)his code. However, he is not informed about the actual
details of the changes. Thus, any comments about the code (and especially
the changes) should not be sent to him. Most of my changes are noted in the
sources with a comment that starts with "MH:".

The code was compiled using SAS/C. Earlier version were compiled with DICE
3.0. GCC and StormC should be able to compile it as well, without any
(large) changes (although I haven't tested this).

The DICE link libraries are created with the help of the LbMake utility in
the DICE package. The file Lib.Def contains the definitions for them.

Notes about the different link libraries:

  · The 'DLib' drawer contains DICE versions of the link libraries, and
    'Lib' contains the SAS/C versions ('Libs' contains the shared library).

  · The asyncio.lib libraries should be used when creating standalone
    versions of the program. The ASIO_NO_EXTERNALS versions will have an
    extra 'e' "flag" in the name.

  · New link libraries with the base name asynciolib.lib are needed if
    you want to use asyncio.library, and don't use the DICE -mi option (or
    perhaps you want to have the autoinit code). Note that there is no
    corresponding SAS/C asynciolib.lib. Link with any of the asyncio*.lib
    link libraries to get the autoinit code, if needed (there is no glue
    available, as I don't want to write it by hand ;).

  · The include file "include/diceclib/asyncio_protos.h" is for DICE 3.0.
    This include file should go to "dinclude:clib" (you only need this to
    use the -mi option to use inline Amiga function calls), whereas the
    other ones should be copied to the respective drawers in
    "dinclude:amiga??/" (DICE) or "include:" (SAS/C).

Notes about how to use the different link libraries:

  · To use the shared library:

    DICE  - Define ASIO_SHARED_LIB and link with asynciolib#?.lib if you
            didn't use the -mi option, or you need the autoinit code.
            Remember that you must copy include/diceclib/asyncio_protos,h
            to dinclude:clib/ if you use the -mi option.

    SAS/C - Include <proto/asyncio.h>, and link with asyncio.lib if you
            need the autoinit code. Currently there is no glue code
            available, so you must include the proto-file. This proto file
            defines ASIO_SHARED_LIB for you.

  · To use the link library for standalone programs:

    Simply link with the appropriate link library, and make sure you only
    define ASIO_REGARGS when you want the regargs version.

    Warning for SAS/C users: If you link with the wrong library, the
    program will link properly, but will show strange errors when run!

    The reason for this "problem" is that I wanted to be able to use the
    regargs version from assembler, without assuming which register
    contained which argument, and then SAS/C does it this way (i.e. no
    difference in function names, as would normally happen for register
    argument functions).

  · To use the "no externals" version of the link library:

    You need to compile the library for starters. ;) Then define
    ASIO_NO_EXTERNALS.

    DICE  - To compile the library simply type e.g. "lbmake asyncio s r e"
            and have dtmp: set to some temporary space. This creates a
            regargs, smalldata version.

    SAS/C - Type e.g. "dmake lib/asyncioer.lib" to get the regargs version.

Notes:

  · When defining any ASIO_#? symbol above, it must be done before any
    asyncio include file is read.

  · I haven't personally tested all combinations above. The shared library
    have had some quick tests, while the "no external" versions of the link
    libraries haven't even been compiled. ;)

  · SAS/C users still need dmake (from DICE) to compile things. This since
    SMake lacks one feature in DMake I find very useful.


  Release 9 - 27-Apr-97
  ---------------------

  · Oops. The include/clib/asyncio_protos.h file wasn't quite correct,
    causing problems when compiling with SAS/C and ASIO_REGARGS defined.
    Also updated includes for StormC. Thanks to Alexander Kazik who sent me
    the needed changes for StormC.

  · Michael B. Smith pointed out that ReadLineAsync() wasn't quite FGets()-
    compatible. So he sent me his version, which was. I've now added his
    version (with some minor changes by me), and changed the implementation
    for ReadLineAsync() to first call the new function FGetsLenAsync(), and
    then skip up to the LF char, for backward compatibility.

  · Added PeekAsync(), to allow you to look ahead in the current buffer
    without actually "reading" anything. Useful when reading from pipes to
    e.g. find out the file type (needed in Visage ;).

  · Bumped the library version to 39, because of the new functions.

  · The autoopen code for SAS/C now uses __asiolibversion rather than
    __oslibversion (in case of failure, __oslibversion is set to the value
    of __asiolibversion, and the standard __autoopenfail is called, in
    order to save code). The default value is 39, and any external
    reference to __asiolibversion will cause the autoopen code to be linked.

  · Ouch. The DMakeFile/lib.def files contained some laws. As a result, the
    DICE linker libraries (in dlib/) were not updated at all. Now there
    should be fresh libraries for both DICE and SAS/C.

  · Fixed a couple of typos in the autodocs, including the problem with the
    enum arguments specified as (U)BYTE, when they need to be LONG (some
    compilers assumes enums to be longs, unless told otherwise).

  Release 8 - 28-Jan-97
  ---------------------

  · Yet another hole in SeekAsync() (hopefully) plugged. ;) Seeking in a
    double-buffered file is tricky business it seems. Thanks to David
    Eaves for finding it, and sending me a good report about it (including
    source to reproduce it).

    The problem was that when SeekAsync() really seeked past the end of the
    file, it didn't notice, and would try to reload the "last" buffer.

  · Finally finished up the ReadLineAsync() function. Only difference from
    dos.library/FGets() should be the return value. I hope it works
    properly, since I haven't tested it that much. ;)

  · Bumped the library version to 38, because of the new functions.

  Release 7 - 7-Jan-96
  --------------------

  · Files to use asyncio.library from E included.

  · Fixed yet some SeekAsync() problems. It could (still) get confused when
    called multiple times in a row with no intervening IO. I wonder if
    there are any holes left. ;)

  · Some more fixes to the shared library.

  · asyncio.library bumped to version 37.2.

  · Recompiled asyncio.library using SAS/C 6.56, and added general SAS/C
    support.

  · Cleaned up parts of this doc.

  Release 6 - 10-Nov-95
  ---------------------

  · Bumped to version 6, since there was an "official" release 3 that I was
    unaware of. However, most of the changes were in the AIFF source (see
    below). Thus, not much was "lost" due to this. (In fact, the SeekAsync
    bugfix in the real release 3 was not correct. ;)

  · Sigh. The SeekAsync fix (to the performance problem) was buggy. :/ I
    think I've got it right now.

  · asyncio.library bumed to version 37.1.

  · Cleaned up this documentation.

  · Fixed some bugs in the include files.

  · Made some fixes to the shared library.

  Release 4 - 13-Sep-95
  ---------------------

  · Oops. Forgot to include the include/asyncio.h file. Maybe as well,
    since I anyway had forgot to mention a few things in it.. ;)

  · Asyncio is now also available as a shared library (to be placed in
    libs:). This means that a couple of new include files were added, and a
    one include file was split up.

    The main reason for doing this was to simplify the use of it in other
    languages (only need to "port" a few includes). I have no other include
    files than those for (DICE) C at the moment, but feel free to send me
    headers for other languages as well.

    Note: I have not yet verified that the SeekAsync function works, but
    since read and write works just fine, I see no reason why SeekAsync
    wouldn't work. ;)

    Also, I haven't really used it in programs much either (only some
    testing), so the different defines and similar to use different
    versions may be a bit clumsy to use (see above for more information).
    Feel free to send me comments on how to improve this.

  · Changed so that a non-regargs version of the link library can be
    created. To use the regargs version now, simply make sure that
    ASIO_REGARGS is defined, and link with the proper link library.

  · Changed the name of the NOEXTERNALS define to ASIO_NOEXTERNALS. Define
    this before you include <clib/asyncio_protos.h> if you want to use that
    feature. Note that you need to create a proper link library yourself!
    (With DICE, all you need to do is "LbMake asyncio s r e" in the Src
    drawer.)

  · Modified OpenAsync() a little, to work around a problem when having
    SnoopDos (with SendARexx active), MungWall and Enforcer running. Not an
    asyncio bug as such, but.. ;)

  Release 3 - 12-Aug-95
  ---------------------

  This version includes a couple of enhancements (most from asyncio code
  found in the sources to the AIFF datatype, by Olaf `Olsen' Barthel) and a
  couple of bugfixes to SeekAsync():

  · SeekAsync() is now not unecessarely slow when doing some "kinds" of
    read-mode seeks (typically when seeking after some small amount of
    initial read). The problem was that it usually only considered the
    newly arrived buffer, not both buffers. This could make it discard both
    buffers, and restart reading, although one of the buffers already had
    the needed data. Note that the kind of seeks that caused the above
    problem may still seem to be somewhat slow, since the code must wait
    for both buffers to be loaded. This cannot (easily) be avoided.

  · SeekAsync() doesn't cause the read buffer to contain garbage after
    certain seeks any more. The problem was that ReadAsync() would read
    from the wrong buffer (the one currently being loaded). This made the
    files seem to contain garbage. This happened when the seek location
    was within the newly arrived buffer.

  · The code package is now supplied as a link library, rather than a
    single source module. The internal functions labeled "AS_#?" are
    private and should not be called directly by the application.

  · A few minor "cosmetic" changes were done, to either make the code more
    readable, or to make it slightly smaller.

  · Include file restructured a little (a public and a private part).

  · OpenAsync() now offers some new "options" (all from the AIFF code by
    Olaf Barthel):
    - Opening a file from an already open filehandle is now possible.
    - A "no externals" version may be compiled, that doesn't require any
       external variables to be available.
    - Each of the buffers will now be roughly bufferSize / 2 bytes large,
       rather than bufferSize bytes (rel 6 note: Really from Taillefers
       third release).
    - If there isn't enough memory for the requested buffer size, the code
       will try with smaller buffers (still properly "aligned") before
       giving up.


asyncio/CloseAsync


   NAME
	CloseAsync -- close an async file.

   SYNOPSIS
	success = CloseAsync( file );
	  d0                   a0

	LONG CloseAsync( struct AsyncFile * );

   FUNCTION
	Closes a file, flushing any pending writes. Once this call has been
	made, the file can no longer be accessed.

   INPUTS
	file - the file to close. May be NULL, in which case this function
	       returns -1 and sets the IoErr() code to ERROR_INVALID_LOCk.

   RESULT
	result - < 0 for an error, >= 0 for success. Indicates whether closing
	    the file worked or not. If the file was opened in read-mode,
	    then this call will always work. In case of error,
		dos.library/IoErr() can give more information.

   SEE ALSO
	OpenAsync(), dos.library/Close()


asyncio/FGetsAsync


   NAME
	FGetsAsync -- read a line from an async file, fgets-style.

   SYNOPSIS
	buffer = FGetsAsync( file, buffer, size );
	  d0                  a0     a1     d0

	APTR ReadLineAsync( struct AsyncFile *, APTR, LONG );

   FUNCTION
	This function reads a single line from an async file, stopping at
	either a NEWLINE character or EOF. In either event, UP TO the
	number of size specified bytes minus 1 will be copied into the
	buffer. It returns the number of bytes put into the buffer,
	excluding the null-termination. 0 indicates EOF, and -1 indicates
	read error.

        If terminated by a newline, the newline WILL be the last character in
        the buffer. The string read in IS null-terminated.

   INPUTS
	file - opened file to read from, as obtained from OpenAsync()
	buffer - buffer to read the line into.
	size - size of the buffer, in bytes.

   RESULT
	buffer - Pointer to buffer passed in, or NULL for immediate EOF or
	    for an error. If NULL is returned for EOF, then
	    dos.library/IoErr() returns 0.

   NOTES
	If the entire line does not fit in the buffer, then the last char
	of the buffer will currently not be used. Don't rely on, nor expect
	this behaviour. It is only mentioned so that you won't send a bug
	report about it. ;)

   SEE ALSO
	OpenAsync(), CloseAsync(), ReadCharAsync(), WriteLineAsync(),
	FGetsLenAsync(), ReadLineAsync(), dos.library/FGets()


asyncio/FGetsLenAsync


   NAME
	FGetsLenAsync -- read a line from an async file.

   SYNOPSIS
	buffer = FGetsLenAsync( file, buffer, size, length );
	  d0                     a0     a1     d0     a2

	APTR FGetsLenAsync( struct AsyncFile *, APTR, LONG, LONG * );

   FUNCTION
	This function reads a single line from an async file, stopping at
	either a NEWLINE character or EOF. In either event, UP TO the
	number of size specified bytes minus 1 will be copied into the
	buffer. It returns the number of bytes put into the buffer,
	excluding the null-termination. 0 indicates EOF, and -1 indicates
	read error.

	If terminated by a newline, the newline WILL be the last character in
	the buffer. The string read in IS null-terminated.

   INPUTS
	file - opened file to read from, as obtained from OpenAsync()
	buffer - buffer to read the line into.
	size - size of the buffer, in bytes.
	length - pointer to ULONG to hold the length of the line, excluding
	    the terminating null.

   RESULT
	buffer - Pointer to buffer passed in, or NULL for immediate EOF or
	    for an error. If NULL is returned for EOF, then
	    dos.library/IoErr() returns 0.

   SEE ALSO
	OpenAsync(), CloseAsync(), ReadCharAsync(), WriteLineAsync(),
	FGetsAsync(), ReadLineAsync(), dos.library/FGets()


asyncio/OpenAsync


   NAME
	OpenAsync -- open a file for asynchronous IO.

   SYNOPSIS
	file = OpenAsync( fileName, accessMode, bufferSize
	 d0                  a0         d0          d1
	                                       [, sysbase, dosbase ] );
	                                            a1       a2

	struct AsyncFile *OpenAsync( const STRPTR, LONG, LONG
	                   [, struct ExecBase *, struct DosLibrary * ] );

	file = OpenAsyncFromFH( handle, accessMode, bufferSize
	                          a0        d0          d1
	                                       [, sysbase, dosbase ] );
	                                            a1       a2

	struct AsyncFile *OpenAsyncFromFH( BPTR, LONG, LONG
	                   [, struct ExecBase *, struct DosLibrary * ] );

   FUNCTION
	The named file is opened and an async file handle returned. If the
	accessMode is MODE_READ, an existing file is opened for reading.
	If accessMode is MODE_WRITE, a new file is created for writing. If
	a file of the same name already exists, it is first deleted. If
	accessMode is MODE_APPEND, an existing file is prepared for writing.
	Data written is added to the end of the file. If the file does not
	exists, it is created.

	'fileName' is a filename and CANNOT be a window specification such as
	CON: or RAW:, or "*"

	'bufferSize' specifies the size of the IO buffer to use. There are
	in fact two buffers allocated, each of roughly (bufferSize/2) bytes
	in size. The actual buffer size use can vary slightly as the size
	is rounded to speed up DMA.

	If the file cannot be opened for any reason, the value returned
	will be NULL, and a secondary error code will be available by
	calling the routine dos.library/IoErr().

    INPUTS
	name - name of the file to open, cannot be a window specification
	accessMode - one of MODE_READ, MODE_WRITE, or MODE_APPEND
	bufferSize - size of IO buffer to use. 8192 is recommended as it
	    provides very good performance for relatively little memory.
	sysbase - Library base needed for the "no externals" version of the
	    library.
	dosbase - Library base, as sysbase.

    RESULTS
	file - an async file handle or NULL for failure. You should not access
	    the fields in the AsyncFile structure, these are private to the
	    async IO routines. In case of failure, dos.library/IoErr() can
	    give more information.

    NOTES (by MH)
	Although stated that CON:, RAW:, or "*" cannot be used as the file
	name, tests indicates that the 2.0+ "Console:" volume is safe to
	use for writing (haven't tested reading). No guarantees though.

    SEE ALSO
	CloseAsync(), dos.library/Open()


asyncio/PeekAsync


   NAME
	PeekAsync -- read bytes from an async file without advancing file
	    pointer.

   SYNOPSIS
	actualLength = PeekAsync( file, buffer, numBytes );
	     d0                    a0     a1       d0

   FUNCTION
	This function tries to read bytes of information from an opened
	async file into the buffer given. 'numBytes' is the number of bytes
	to read from the file.

	The read is done without advancing the file pointer, and the read
	is limited to what is available in the current buffer (or the next
	buffer, if the current buffer is empty). If the current buffer does
	not contain 'numBytes' bytes, only the bytes left in the buffer is
	read.

	Using PeekAsync() can remove the need to SeekAsync() back after some
	ReadAsync() calls (making your read operations more pipe friendly).

	The value returned is the length of the information actually read.
	So, when 'actualLength' is greater than zero, the value of
	'actualLength' is the the number of characters read. A value of
	zero means that end-of-file has been reached. Errors are indicated
	by a value of -1.

    INPUTS
	file - opened file to read, as obtained from OpenAsync()
	buffer - buffer where to put bytes read
	numBytes - number of bytes to read into buffer

    RESULT
	actualLength - actual number of bytes read, or -1 if an error. In
	    case of error, dos.library/IoErr() can give more information.

    SEE ALSO
	OpenAsync(), CloseAsync(), ReadCharAsync(), WriteAsync(),
	dos.library/Read()



asyncio/ReadAsync


   NAME
	ReadAsync -- read bytes from an async file.

   SYNOPSIS
	actualLength = ReadAsync( file, buffer, numBytes );
	     d0                    a0     a1       d0

	LONG ReadAsync( struct AsyncFile *, APTR, LONG );

   FUNCTION
	This function reads bytes of information from an opened async file
	into the buffer given. 'numBytes' is the number of bytes to read from
	the file.

	The value returned is the length of the information actually read.
	So, when 'actualLength' is greater than zero, the value of
	'actualLength' is the the number of characters read. Usually
	ReadAsync() will try to fill up your buffer before returning. A value
	of zero means that end-of-file has been reached. Errors are indicated
	by a value of -1.

    INPUTS
	file - opened file to read, as obtained from OpenAsync()
	buffer - buffer where to put bytes read
	numBytes - number of bytes to read into buffer

    RESULT
	actualLength - actual number of bytes read, or -1 if an error. In
	    case of error, dos.library/IoErr() can give more information.

    SEE ALSO
	OpenAsync(), CloseAsync(), ReadCharAsync(), WriteAsync(),
	dos.library/Read()


asyncio/ReadCharAsync


   NAME
	ReadCharAsync -- read a single byte from an async file.

   SYNOPSIS
	byte = ReadCharAsync( file );
	 d0                    a0

	LONG ReadCharAsync( struct AsyncFile * );

   FUNCTION
	This function reads a single byte from an async file. The byte is
	returned, or -1 if there was an error reading, or if the end-of-file
	was reached.

   INPUTS
	file - opened file to read from, as obtained from OpenAsync()

   RESULT
	byte - the byte read, or -1 if no byte was read. In case of error,
	    dos.library/IoErr() can give more information. If IoErr()
	    returns 0, it means end-of-file was reached. Any other value
	    indicates an error.

   SEE ALSO
	OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync()
	dos.library/Read()


asyncio/ReadLineAsync


   NAME
	ReadLineAsync -- read a line from an async file.

   SYNOPSIS
	bytes = ReadLineAsync( file, buffer, size );
	 d0                     a0     a1     d0

	LONG ReadLineAsync( struct AsyncFile *, APTR, ULONG );

   FUNCTION
	This function reads a single line from an async file, stopping at
	either a NEWLINE character or EOF. In either event, UP TO the
	number of size specified bytes minus 1 will be copied into the
	buffer. It returns the number of bytes put into the buffer,
	excluding the null-termination. 0 indicates EOF, and -1 indicates
	read error.

	If the line in the file is longer than the buffer, the line will be
	truncated (any newline will be present). Any data left in the file
	upto the newline will be lost.

	If terminated by a newline, the newline WILL be the last character in
	the buffer. The string read in IS null-terminated.

   INPUTS
	file - opened file to read from, as obtained from OpenAsync()
	buffer - buffer to read the line into.
	size - size of the buffer, in bytes.

   RESULT
	bytes - number of bytes read. In case of error (-1 is returned)
	    dos.library/IoErr() can give more information. EOF is indicated
	    by a return of 0.

   SEE ALSO
	OpenAsync(), CloseAsync(), ReadCharAsync(), FGetsAsync(),
	WriteLineAsync(), dos.library/FGets()


asyncio/SeekAsync


   NAME
	SeekAsync -- set the current position for reading or writing within
	    an async file.

   SYNOPSIS
	oldPosition = SeekAsync( file, position, mode );
	     d0                   a0      d0      d1

	LONG SeekAsync( struct AsyncFile *, LONG, LONG );

   FUNCTION
	SeekAsync() sets the read/write cursor for the file 'file' to the
	position 'position'. This position is used by the various read/write
	functions as the place to start reading or writing. The result is the
	current absolute position in the file, or -1 if an error occurs, in
	which case dos.library/IoErr() can be used to find more information.
	'mode' can be MODE_START, MODE_CURRENT or MODE_END. It is used to
	specify the relative start position. For example, 20 from current
	is a position 20 bytes forward from current, -20 is 20 bytes back
	from current.

	To find out what the current position within a file is, simply seek
	zero from current.

    INPUTS
	file - an opened async file, as obtained from OpenAsync()
	position - the place where to move the read/write cursor
	mode - the mode for the position, one of MODE_START, MODE_CURRENT,
	    or MODE_END.

    RESULT
	oldPosition - the previous position of the read/write cursor, or -1
	    if an error occurs. In case of error, dos.library/IoErr() can
	    give more information.

    NOTES (by MH)
	If you seek after having read only a few bytes, the function must
	wait for both buffers to be loaded, before the seek can be done.
	This can cause small delays. Note that the above case isn't the
	only one, but the typical one.

    SEE ALSO
	OpenAsync(), CloseAsync(), ReadAsync(), WriteAsync(),
	dos.library/Seek()


asyncio/WriteAsync


   NAME
	WriteAsync -- write data to an async file.

   SYNOPSIS
	actualLength = WriteAsync( file, buffer, numBytes );
	     d0                     a0     a1       d0

	LONG WriteAsync( struct AsyncFile *, APTR, LONG );

   FUNCTION
	WriteAsync() writes bytes of data to an opened async file. 'numBytes'
	indicates the number of bytes of data to be transferred. 'buffer'
	points to the data to write. The value returned is the length of
	information actually written. So, when 'actualLength' is greater
	than zero, the value of 'actualLength' is the number of characters
	written. Errors are indicated by a return value of -1.

    INPUTS
	file - an opened file, as obtained from OpenAsync()
	buffer - address of data to write
	numBytes - number of bytes to write to the file

    RESULT
	actualLength - number of bytes written, or -1 if error. In case
	    of error, dos.library/IoErr() can give more information.

    SEE ALSO
	OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync(),
	dos.library/Write()


asyncio/WriteCharAsync


   NAME
	WriteCharAsync -- write a single byte to an async file.

   SYNOPSIS
	result = WriteCharAsync( file, byte );
	  d0                      a0    d0

	LONG WriteCharAsync( struct AsyncFile *, UBYTE );

   FUNCTION
	This function writes a single byte to an async file.

   INPUTS
	file - an opened async file, as obtained from OpenAsync()
	byte - byte of data to add to the file

   RESULT
	result - 1 if the byte was written, -1 if there was an error. In
	    case of error, dos.library/IoErr() can give more information.

   SEE ALSO
	OpenAsync(), CloseAsync(), ReadAsync(), WriteAsync(),
	dos.library/Write()


asyncio/WriteLineAsync


   NAME
	WriteLineAsync -- write a line to an async file.

   SYNOPSIS
	bytes = WriteLineAsync(file, buffer);

	LONG WriteLineAsync(struct AsyncFile *, STRPTR);

   FUNCTION
	This function writes an unformatted string to an async file. No
	newline is appended to the string.

   INPUTS
	file - opened file to read from, as obtained from OpenAsync()
	buffer - buffer to write to the file

   RESULT
	bytes - number of bytes written, or -1 if there was an error. In
	    case of error, dos.library/IoErr() can give more information.

   SEE ALSO
	OpenAsync(), CloseAsync(), ReadCharAsync(), WriteCharAsync(),
	FGetsAsync(), FGetsLenAsync(), ReadLineAsync(), dos.library/FPuts()


Converted on 22 Apr 2000 with RexxDoesAmigaGuide2HTML 2.1 by Michael Ranner.