home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / c / AsyncIO.lha / AsyncIO / asyncio.doc next >
Encoding:
Text File  |  1997-01-28  |  25.3 KB  |  679 lines

  1. TABLE OF CONTENTS
  2.  
  3. asyncio/--background--
  4. asyncio/--history--
  5. asyncio/--changes--
  6. asyncio/CloseAsync
  7. asyncio/OpenAsync
  8. asyncio/ReadAsync
  9. asyncio/ReadCharAsync
  10. asyncio/ReadLineAsync
  11. asyncio/SeekAsync
  12. asyncio/WriteAsync
  13. asyncio/WriteCharAsync
  14. asyncio/WriteLineAsync
  15. asyncio/--background--                                 asyncio/--background--
  16.  
  17. This documentation and source code was written by Martin Taillefer.
  18.  
  19. Reading and writing data is crucial to most applications and is in many cases
  20. a major bottleneck. Using AmigaDOS' sophisticated file system architecture
  21. can help reduce, and sometimes eliminate, the time spent waiting for IO to
  22. complete. This package offers a few small routines that can greatly improve
  23. an application's IO performance.
  24.  
  25. Normally, an application processes a file in a manner similar to the following:
  26.  
  27.   1 - Open the file
  28.  
  29.   2 - Read some data
  30.  
  31.   3 - Process data just read
  32.  
  33.   4 - Repeat steps 2 and 3 until all data is processed
  34.  
  35.   5 - Close file
  36.  
  37. Although the above sequence works fine, it doesn't make full use of the Amiga's
  38. multitasking abilities. Step 2 in the above can become a serious bottleneck.
  39. Whenever the application needs some data by using the DOS Read() function,
  40. AmigaDOS has to put that task to sleep, and initiate a request to the file
  41. system to have it fetch the data. The file system then starts up the disk
  42. hardware and reads the data. Once the data is read, the application is woken up
  43. and can start processing the data just read.
  44.  
  45. The point to note in the above paragraph is that when the file system is
  46. reading data from disk, the application is asleep. Wouldn't it be nice if the
  47. application could keep running while data is being fetched for it?
  48.  
  49. Most Amiga hard drives make use of DMA (Direct Memory Access). DMA enables a
  50. hard drive to transfer data to memory _at the same time_ as the CPU does some
  51. work. This parallelism is what makes the set of accompanying routines so
  52. efficient. They exploit the fact that data can be transfered to memory while
  53. the application is busy processing other data.
  54.  
  55. Using the asynchronous IO routines, an application's IO happens like this:
  56.  
  57.   1 - Open the file, ask the file system to start reading ahead
  58.  
  59.   2 - Read some data, ask the file system to read more data
  60.  
  61.   3 - Process data
  62.  
  63.   4 - Repeat steps 2 and 3 until all data is processed
  64.  
  65.   5 - Close file
  66.  
  67. Immediately after opening the file, a request is sent to the file system to get
  68. it reading data in the background. By the time the application gets around to
  69. reading the first byte of data, it is likely already in memory. That means the
  70. application doesn't need to wait and can start processing the data. As soon as
  71. the application starts processing data from the file, a second request is sent
  72. out to the file system to fill up a second buffer. Once the application is done
  73. processing the first buffer, it starts processing the second one. When this
  74. happens, the file system starts filling up the first buffer again with new
  75. data. This process continues until all data has been read.
  76.  
  77. The whole technique is known as "double-buffered asynchronous IO" since it uses
  78. two buffers, and happens in the background (asynchronously).
  79.  
  80. The set of functions presented below offers high-performance IO using the
  81. technique described above. The interface is very similar to standard AmigaDOS
  82. files. These routines enable full asynchronous read/write of any file.
  83.  
  84. asyncio/--history--                                       asyncio/--history--
  85.  
  86. 23-Mar-94
  87. ---------
  88.  
  89.   - When seeking within the current read buffer, the wrong packet would be
  90.     sent out to be filled asynchronously. Depending on the data read from
  91.     the buffer, and how fast it was read, you could end up getting incorrect
  92.     data on subsequent ReadAsync() calls.
  93.  
  94.   - There was actually bufferSize*2 bytes allocated for IO buffers instead
  95.     of just bufferSize. This is fixed. So if you want the same effective
  96.     buffer size as before, you must double the value of the bufferSize
  97.     argument supplied to OpenAsync().
  98.  
  99.   - MEMF_PUBLIC is now specified for the IO buffers. This is in support
  100.     of VM hacks such as GigaMem.
  101.  
  102.   - A Seek() call had the mode and offset parameters reversed. The code worked,
  103.     because both values were luckily always 0, but it was not very clean.
  104.  
  105.   - Now uses a typedef for the AsyncFile structure, and enums for the
  106.     open modes and seek modes.
  107.  
  108. 16-Feb-94
  109. ---------
  110.  
  111.   - SeekAsync() now consistently works. It was getting confused when called
  112.     multiple times in a row with no intervening IO.
  113.  
  114.   - WriteAsync() would produce garbage in the destination file if it had
  115.     to bring up a "Disk is full" requester, and the user freed some room on
  116.     the disk and selected "Retry".
  117.  
  118. asyncio/--changes--                                       asyncio/--changes--
  119.  
  120. All changes described in this section were made by Magnus Holmgren. If you
  121. want to contact me about something, feel free to send a message to
  122. cmh@lls.se or "Magnus Holmgren", 2:203/512.10@fidonet.org.
  123.  
  124. I've been in contact with Martin Taillefer, and he is aware of me releasing
  125. new versions of (t)his code. However, he is not informed about the actual
  126. details of the changes. Thus, any comments about the code (and especially
  127. the changes) should not be sent to him. Most of my changes are noted in the
  128. sources with a comment that starts with "MH:".
  129.  
  130. The code was compiled using SAS/C. Earlier version were compiled with DICE
  131. 3.0. GCC should be able to compile it as well, without any (large) changes
  132. (although I haven't tested this).
  133.  
  134. The DICE link libraries are created with the help of the LbMake utility in
  135. the DICE package. The file Lib.Def contains the definitions for them.
  136.  
  137. Notes about the different link libraries:
  138.  
  139.   · The 'DLib' drawer contains DICE versions of the link libraries, and
  140.     'Lib' contains the SAS/C versions ('Libs' contains the shared library).
  141.  
  142.   · The asyncio.lib libraries should be used when creating standalone
  143.     versions of the program. The ASIO_NO_EXTERNALS versions will have an
  144.     extra 'e' "flag" in the name.
  145.  
  146.   · New link libraries with the base name asynciolib.lib are needed if
  147.     you want to use asyncio.library, and don't use the DICE -mi option (or
  148.     perhaps you want to have the autoinit code). Note that there is no
  149.     corresponding SAS/C asynciolib.lib. Link with any of the asyncio*.lib
  150.     link libraries to get the autoinit code, if needed (there is no glue
  151.     available, as I don't want to write it by hand ;).
  152.  
  153.   · The include file "include/diceclib/asyncio_protos.h" is for DICE 3.0.
  154.     This include file should go to "dinclude:clib" (you only need this to
  155.     use the -mi option to use inline Amiga function calls), whereas the
  156.     other ones should be copied to the respective drawers in
  157.     "dinclude:amiga??/" (DICE) or "include:" (SAS/C).
  158.  
  159. Notes about how to use the different link libraries:
  160.  
  161.   · To use the shared library:
  162.  
  163.     DICE  - Define ASIO_SHARED_LIB and link with asynciolib#?.lib if you
  164.             didn't use the -mi option, or you need the autoinit code.
  165.             Remember that you must copy include/diceclib/asyncio_protos,h
  166.             to dinclude:clib/ if you use the -mi option.
  167.  
  168.     SAS/C - Include <proto/asyncio.h>, and link with asyncio.lib if you
  169.             need the autoinit code. Currently there is no glue code
  170.             available, so you must include the proto-file. This proto file
  171.             defines ASIO_SHARED_LIB for you.
  172.  
  173.   · To use the link library for standalone programs:
  174.  
  175.     Simply link with the appropriate link library, and make sure you only
  176.     define ASIO_REGARGS when you want the regargs version.
  177.  
  178.     Warning for SAS/C users: If you link with the wrong library, the
  179.     program will link properly, but will show strange errors when run! 
  180.     
  181.     The reason for this "problem" is that I wanted to be able to use the
  182.     regargs version from assembler, and then SAS/C does it this way (i.e.
  183.     no difference in function names, as would normally happen for register
  184.     argument functions).
  185.  
  186.   · To use the "no externals" version of the link library:
  187.  
  188.     You need to compile the library for starters. ;) Then define
  189.     ASIO_NO_EXTERNALS.
  190.  
  191.     DICE  - To compile the library simply type e.g. "lbmake asyncio s r e"
  192.             and have dtmp: set to some temporary space. This creates a
  193.             regargs, smalldata version.
  194.  
  195.     SAS/C - Type e.g. "dmake lib/asyncioer.lib" to get the regargs version.
  196.  
  197. Notes:
  198.  
  199.   · When defining any ASIO_#? symbol above, it must be done before any
  200.     asyncio include file is read.
  201.  
  202.   · I haven't personally tested all combinations above. The shared library
  203.     have had some quick tests, while the "no external" versions of the link
  204.     libraries haven't even been compiled. ;)
  205.  
  206.   · SAS/C users still need dmake (from DICE) to compile things. This since
  207.     SMake lacks one feature in DMake I find very useful.
  208.  
  209.  
  210.   Release 8 - 28-Jan-97
  211.   ---------------------
  212.  
  213.   · Yet another hole in SeekAsync() (hopefully) plugged. ;) Seeking in a
  214.     double-buffered file is tricky business it seems. Thanks to David
  215.     Eaves for finding it, and sending me a good report about it (including
  216.     source to reproduce it).
  217.  
  218.     The problem was that when SeekAsync() really seeked past the end of the
  219.     file, it didn't notice, and would try to reload the "last" buffer.
  220.  
  221.   · Finally finished up the ReadLineAsync() function. Only difference from
  222.     dos.library/FGets() should be the return value. I hope it works
  223.     properly, since I haven't tested it that much. ;)
  224.     
  225.   · Bumped the library version to 38, because of the new functions.
  226.  
  227.   Release 7 - 7-Jan-96
  228.   --------------------
  229.  
  230.   · Files to use asyncio.library from E included.
  231.  
  232.   · Fixed yet some SeekAsync() problems. It could (still) get confused when
  233.     called multiple times in a row with no intervening IO. I wonder if
  234.     there are any holes left. ;)
  235.  
  236.   · Some more fixes to the shared library.
  237.  
  238.   · asyncio.library bumped to version 37.2.
  239.  
  240.   · Recompiled asyncio.library using SAS/C 6.56, and added general SAS/C
  241.     support.
  242.  
  243.   · Cleaned up parts of this doc.
  244.  
  245.   Release 6 - 10-Nov-95
  246.   ---------------------
  247.  
  248.   · Bumped to version 6, since there was an "official" release 3 that I was
  249.     unaware of. However, most of the changes were in the AIFF source (see
  250.     below). Thus, not much was "lost" due to this. (In fact, the SeekAsync
  251.     bugfix in the real release 3 was not correct. ;)
  252.  
  253.   · Sigh. The SeekAsync fix (to the performance problem) was buggy. :/ I
  254.     think I've got it right now.
  255.  
  256.   · asyncio.library bumed to version 37.1.
  257.  
  258.   · Cleaned up this documentation.
  259.  
  260.   · Fixed some bugs in the include files.
  261.  
  262.   · Made some fixes to the shared library.
  263.  
  264.   Release 4 - 13-Sep-95
  265.   ---------------------
  266.  
  267.   · Oops. Forgot to include the include/asyncio.h file. Maybe as well,
  268.     since I anyway had forgot to mention a few things in it.. ;)
  269.  
  270.   · Asyncio is now also available as a shared library (to be placed in
  271.     libs:). This means that a couple of new include files were added, and a
  272.     one include file was split up.
  273.  
  274.     The main reason for doing this was to simplify the use of it in other
  275.     languages (only need to "port" a few includes). I have no other include
  276.     files than those for (DICE) C at the moment, but feel free to send me
  277.     headers for other languages as well.
  278.  
  279.     Note: I have not yet verified that the SeekAsync function works, but
  280.     since read and write works just fine, I see no reason why SeekAsync
  281.     wouldn't work. ;)
  282.  
  283.     Also, I haven't really used it in programs much either (only some
  284.     testing), so the different defines and similar to use different
  285.     versions may be a bit clumsy to use (see above for more information).
  286.     Feel free to send me comments on how to improve this.
  287.  
  288.   · Changed so that a non-regargs version of the link library can be
  289.     created. To use the regargs version now, simply make sure that
  290.     ASIO_REGARGS is defined, and link with the proper link library.
  291.  
  292.   · Changed the name of the NOEXTERNALS define to ASIO_NOEXTERNALS. Define
  293.     this before you include <clib/asyncio_protos.h> if you want to use that
  294.     feature. Note that you need to create a proper link library yourself!
  295.     (With DICE, all you need to do is "LbMake asyncio s r e" in the Src
  296.     drawer.)
  297.  
  298.   · Modified OpenAsync() a little, to work around a problem when having
  299.     SnoopDos (with SendARexx active), MungWall and Enforcer running. Not an
  300.     asyncio bug as such, but.. ;)
  301.  
  302.   Release 3 - 12-Aug-95
  303.   ---------------------
  304.  
  305.   This version includes a couple of enhancements (most from asyncio code
  306.   found in the sources to the AIFF datatype, by Olaf `Olsen' Barthel) and a
  307.   couple of bugfixes to SeekAsync():
  308.  
  309.   · SeekAsync() is now not unecessarely slow when doing some "kinds" of
  310.     read-mode seeks (typically when seeking after some small amount of
  311.     initial read). The problem was that it usually only considered the
  312.     newly arrived buffer, not both buffers. This could make it discard both
  313.     buffers, and restart reading, although one of the buffers already had
  314.     the needed data. Note that the kind of seeks that caused the above
  315.     problem may still seem to be somewhat slow, since the code must wait
  316.     for both buffers to be loaded. This cannot (easily) be avoided.
  317.  
  318.   · SeekAsync() doesn't cause the read buffer to contain garbage after
  319.     certain seeks any more. The problem was that ReadAsync() would read
  320.     from the wrong buffer (the one currently being loaded). This made the
  321.     files seem to contain garbage. This happened when the seek location
  322.     was within the newly arrived buffer.
  323.  
  324.   · The code package is now supplied as a link library, rather than a
  325.     single source module. The internal functions labeled "AS_#?" are
  326.     private and should not be called directly by the application.
  327.  
  328.   · A few minor "cosmetic" changes were done, to either make the code more
  329.     readable, or to make it slightly smaller.
  330.  
  331.   · Include file restructured a little (a public and a private part).
  332.  
  333.   · OpenAsync() now offers some new "options" (all from the AIFF code by
  334.     Olaf Barthel):
  335.     - Opening a file from an already open filehandle is now possible.
  336.     - A "no externals" version may be compiled, that doesn't require any
  337.        external variables to be available.
  338.     - Each of the buffers will now be roughly bufferSize / 2 bytes large,
  339.        rather than bufferSize bytes (rel 6 note: Really from Taillefers
  340.        third release).
  341.     - If there isn't enough memory for the requested buffer size, the code
  342.        will try with smaller buffers (still properly "aligned") before
  343.        giving up.
  344.  
  345. asyncio/CloseAsync                                         asyncio/CloseAsync
  346.  
  347.    NAME
  348.     CloseAsync -- close an async file.
  349.  
  350.    SYNOPSIS
  351.     success = CloseAsync( file );
  352.       d0                   a0
  353.  
  354.     LONG CloseAsync( struct AsyncFile * );
  355.  
  356.    FUNCTION
  357.     Closes a file, flushing any pending writes. Once this call has been
  358.     made, the file can no longer be accessed.
  359.  
  360.    INPUTS
  361.     file - the file to close. May be NULL, in which case this function
  362.            returns -1 and sets the IoErr() code to ERROR_INVALID_LOCk.
  363.  
  364.    RESULT
  365.     result - < 0 for an error, >= 0 for success. Indicates whether closing
  366.          the file worked or not. If the file was opened in read-mode,
  367.              then this call will always work. In case of error,
  368.              dos.library/IoErr() can give more information.
  369.  
  370.    SEE ALSO
  371.     OpenAsync(), dos.library/Close()
  372.  
  373. asyncio/OpenAsync                                           asyncio/OpenAsync
  374.  
  375.    NAME
  376.     OpenAsync -- open a file for asynchronous IO.
  377.  
  378.    SYNOPSIS
  379.     file = OpenAsync( fileName, accessMode, bufferSize
  380.      d0                  a0         d0          d1
  381.                                            [, sysbase, dosbase ] );
  382.                                                 a1       a2
  383.  
  384.     struct AsyncFile OpenAsync( const STRPTR, UBYTE, LONG
  385.                        [, struct ExecBase *, struct DosLibrary * ] );
  386.  
  387.     file = OpenAsyncFromFH( handle, accessMode, bufferSize
  388.                               a0        d0          d1
  389.                                            [, sysbase, dosbase ] );
  390.                                                 a1       a2
  391.  
  392.     struct AsyncFile OpenAsyncFromFH( BPTR, UBYTE, LONG
  393.                        [, struct ExecBase *, struct DosLibrary * ] );
  394.  
  395.    FUNCTION
  396.     The named file is opened and an async file handle returned. If the
  397.     accessMode is MODE_READ, an existing file is opened for reading.
  398.     If accessMode is MODE_WRITE, a new file is created for writing. If
  399.     a file of the same name already exists, it is first deleted. If
  400.     accessMode is MODE_APPEND, an existing file is prepared for writing.
  401.     Data written is added to the end of the file. If the file does not
  402.     exists, it is created.
  403.  
  404.     'fileName' is a filename and CANNOT be a window specification such as
  405.     CON: or RAW:, or "*"
  406.  
  407.     'bufferSize' specifies the size of the IO buffer to use. There are
  408.     in fact two buffers allocated, each of roughly (bufferSize/2) bytes
  409.     in size. The actual buffer size use can vary slightly as the size
  410.     is rounded to speed up DMA.
  411.  
  412.     If the file cannot be opened for any reason, the value returned
  413.     will be NULL, and a secondary error code will be available by
  414.     calling the routine dos.library/IoErr().
  415.  
  416.     INPUTS
  417.     name - name of the file to open, cannot be a window specification
  418.     accessMode - one of MODE_READ, MODE_WRITE, or MODE_APPEND
  419.     bufferSize - size of IO buffer to use. 8192 is recommended as it
  420.              provides very good performance for relatively little
  421.              memory.
  422.     sysbase - Library base needed for the "no externals" version of the
  423.         library.
  424.     dosbase - Library base, as sysbase.
  425.  
  426.     RESULTS
  427.     file - an async file handle or NULL for failure. You should not access
  428.            the fields in the AsyncFile structure, these are private to the
  429.            async IO routines. In case of failure, dos.library/IoErr() can
  430.            give more information.
  431.  
  432.     NOTES (by MH)
  433.     Although stated that CON:, RAW:, or "*" cannot be used as the file
  434.     name, tests indicates that the 2.0+ "Console:" volume is safe to
  435.     use for writing (haven't tested reading). No guarantees though.
  436.  
  437.     SEE ALSO
  438.     CloseAsync(), dos.library/Open()
  439.  
  440. asyncio/ReadAsync                                           asyncio/ReadAsync
  441.  
  442.    NAME
  443.     ReadAsync -- read bytes from an async file.
  444.  
  445.    SYNOPSIS
  446.     actualLength = ReadAsync( file, buffer, numBytes );
  447.          d0                    a0     a1       d0
  448.  
  449.     LONG ReadAsync( struct AsyncFile *, APTR, LONG );
  450.  
  451.    FUNCTION
  452.     This function reads bytes of information from an opened async file
  453.         into the buffer given. 'numBytes' is the number of bytes to read from
  454.         the file.
  455.  
  456.     The value returned is the length of the information actually read.
  457.     So, when 'actualLength' is greater than zero, the value of
  458.     'actualLength' is the the number of characters read. Usually
  459.     ReadAsync() will try to fill up your buffer before returning. A value
  460.     of zero means that end-of-file has been reached. Errors are indicated
  461.     by a value of -1.
  462.  
  463.     INPUTS
  464.     file - opened file to read, as obtained from OpenAsync()
  465.     buffer - buffer where to put bytes read
  466.     numBytes - number of bytes to read into buffer
  467.  
  468.     RESULT
  469.     actualLength - actual number of bytes read, or -1 if an error. In
  470.                case of error, dos.library/IoErr() can give more
  471.                information.
  472.  
  473.     SEE ALSO
  474.     OpenAsync(), CloseAsync(), ReadCharAsync(), WriteAsync(),
  475.     dos.library/Read()
  476.  
  477. asyncio/ReadCharAsync                                   asyncio/ReadCharAsync
  478.  
  479.    NAME
  480.     ReadCharAsync -- read a single byte from an async file.
  481.  
  482.    SYNOPSIS
  483.     byte = ReadCharAsync( file );
  484.      d0                    a0
  485.  
  486.     LONG ReadCharAsync( struct AsyncFile * );
  487.  
  488.    FUNCTION
  489.     This function reads a single byte from an async file. The byte is
  490.     returned, or -1 if there was an error reading, or if the end-of-file
  491.     was reached.
  492.  
  493.    INPUTS
  494.     file - opened file to read from, as obtained from OpenAsync()
  495.  
  496.    RESULT
  497.     byte - the byte read, or -1 if no byte was read. In case of error,
  498.            dos.library/IoErr() can give more information. If IoErr()
  499.            returns 0, it means end-of-file was reached. Any other value
  500.            indicates an error.
  501.  
  502.    SEE ALSO
  503.     OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync()
  504.     dos.library/Read()
  505.  
  506. asyncio/ReadLineAsync                                   asyncio/ReadLineAsync
  507.  
  508.    NAME
  509.     ReadLineAsync -- read a line from an async file.
  510.  
  511.    SYNOPSIS
  512.     bytes = ReadLineAsync( file, buffer, size );
  513.      d0                     a0     a1     d0
  514.  
  515.     LONG ReadLineAsync( struct AsyncFile *, STRPTR, ULONG );
  516.  
  517.    FUNCTION
  518.     This function reads a single line from an async file, stopping at
  519.     either a NEWLINE character or EOF. In either event, UP TO the
  520.     number of size specified bytes minus 1 will be copied into the
  521.     buffer. It returns the number of bytes put into the buffer,
  522.     excluding the null-termination. 0 indicates EOF, and -1 indicates
  523.     read error.
  524.  
  525.     If the line in the file is longer than the buffer, the line will be
  526.     truncated (any newline will be present). Any data left in the file
  527.         upto the newline will be lost.
  528.  
  529.         If terminated by a newline, the newline WILL be the last character in
  530.         the buffer. The string read in IS null-terminated.
  531.  
  532.    INPUTS
  533.     file - opened file to read from, as obtained from OpenAsync()
  534.     buffer - buffer to read the line into.
  535.     size - size of the buffer, in bytes.
  536.  
  537.    RESULT
  538.     bytes - number of bytes read. In case of error (-1 is returned)
  539.             dos.library/IoErr() can give more information. EOF is
  540.             indicated by a return of 0.
  541.  
  542.    SEE ALSO
  543.     OpenAsync(), CloseAsync(), ReadCharAsync(), WriteLineAsync(),
  544.     dos.library/FGets()
  545.  
  546. asyncio/SeekAsync                                           asyncio/SeekAsync
  547.  
  548.    NAME
  549.     SeekAsync -- set the current position for reading or writing within
  550.              an async file.
  551.  
  552.    SYNOPSIS
  553.     oldPosition = SeekAsync( file, position, mode );
  554.          d0                   a0      d0      d1
  555.  
  556.     LONG SeekAsync( struct AsyncFile *, LONG, BYTE );
  557.  
  558.    FUNCTION
  559.     SeekAsync() sets the read/write cursor for the file 'file' to the
  560.     position 'position'. This position is used by the various read/write
  561.     functions as the place to start reading or writing. The result is the
  562.     current absolute position in the file, or -1 if an error occurs, in
  563.     which case dos.library/IoErr() can be used to find more information.
  564.     'mode' can be MODE_START, MODE_CURRENT or MODE_END. It is used to
  565.     specify the relative start position. For example, 20 from current
  566.     is a position 20 bytes forward from current, -20 is 20 bytes back
  567.     from current.
  568.  
  569.     To find out what the current position within a file is, simply seek
  570.     zero from current.
  571.  
  572.     INPUTS
  573.     file - an opened async file, as obtained from OpenAsync()
  574.     position - the place where to move the read/write cursor
  575.     mode - the mode for the position, one of MODE_START, MODE_CURRENT,
  576.            or MODE_END.
  577.  
  578.     RESULT
  579.     oldPosition - the previous position of the read/write cursor, or -1
  580.               if an error occurs. In case of error, dos.library/IoErr()
  581.               can give more information.
  582.  
  583.     NOTES (by MH)
  584.     If you seek after having read only a few bytes, the function must
  585.     wait for both buffers to be loaded, before the seek can be done.
  586.     This can cause small delays. Note that the above case isn't the
  587.     only one, but the typical one.
  588.  
  589.     SEE ALSO
  590.     OpenAsync(), CloseAsync(), ReadAsync(), WriteAsync(),
  591.     dos.library/Seek()
  592.  
  593. asyncio/WriteAsync                                         asyncio/WriteAsync
  594.  
  595.    NAME
  596.     WriteAsync -- write data to an async file.
  597.  
  598.    SYNOPSIS
  599.     actualLength = WriteAsync( file, buffer, numBytes );
  600.          d0                     a0     a1       d0
  601.  
  602.     LONG WriteAsync( struct AsyncFile *, APTR, LONG );
  603.  
  604.    FUNCTION
  605.     WriteAsync() writes bytes of data to an opened async file. 'numBytes'
  606.     indicates the number of bytes of data to be transferred. 'buffer'
  607.     points to the data to write. The value returned is the length of
  608.     information actually written. So, when 'numBytes' is greater than
  609.     zero, the value of 'numBytes' is the number of characters written.
  610.     Errors are indicated by a return value of -1.
  611.  
  612.     INPUTS
  613.     file - an opened file, as obtained from OpenAsync()
  614.     buffer - address of data to write
  615.     numBytes - number of bytes to write to the file
  616.  
  617.     RESULT
  618.     actualLength - number of bytes written, or -1 if error. In case
  619.                of error, dos.library/IoErr() can give more
  620.                information.
  621.  
  622.     SEE ALSO
  623.     OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync(),
  624.     dos.library/Write()
  625.  
  626. asyncio/WriteCharAsync                                 asyncio/WriteCharAsync
  627.  
  628.    NAME
  629.     WriteCharAsync -- write a single byte to an async file.
  630.  
  631.    SYNOPSIS
  632.     result = WriteCharAsync( file, byte );
  633.       d0                      a0    d0
  634.  
  635.     LONG WriteCharAsync( struct AsyncFile *, UBYTE );
  636.  
  637.    FUNCTION
  638.     This function writes a single byte to an async file.
  639.  
  640.    INPUTS
  641.     file - an opened async file, as obtained from OpenAsync()
  642.     byte - byte of data to add to the file
  643.  
  644.    RESULT
  645.     result - 1 if the byte was written, -1 if there was an error. In
  646.          case of error, dos.library/IoErr() can give more information.
  647.  
  648.    SEE ALSO
  649.     OpenAsync(), CloseAsync(), ReadAsync(), WriteAsync(),
  650.     dos.library/Write()
  651.  
  652. asyncio/WriteLineAsync                                 asyncio/WriteLineAsync
  653.  
  654.    NAME
  655.     WriteLineAsync -- write a line to an async file.
  656.  
  657.    SYNOPSIS
  658.     bytes = WriteLineAsync(file, buffer);
  659.  
  660.     LONG WriteLineAsync(struct AsyncFile *, STRPTR);
  661.  
  662.    FUNCTION
  663.     This function writes an unformatted string to an async file. No
  664.     newline is appended to the string.
  665.  
  666.    INPUTS
  667.     file - opened file to read from, as obtained from OpenAsync()
  668.     buffer - buffer to write to the file
  669.  
  670.    RESULT
  671.     bytes - number of bytes written, or -1 if there was an error. In
  672.             case of error, dos.library/IoErr() can give more
  673.             information.
  674.  
  675.    SEE ALSO
  676.     OpenAsync(), CloseAsync(), ReadCharAsync(), WriteCharAsync(),
  677.     WriteLineAsync(), dos.library/FPuts()
  678.  
  679.