00001 // This is oul/oufgl/asyncio.h 00002 #ifndef OTAGO_Asyncio_IO__h_INCLUDED 00003 #define OTAGO_Asyncio_IO__h_INCLUDED 00004 //: 00005 // \file 00006 // \brief A simple wrapper around POSIX.1b asynchronous I/O 00007 // 00008 // Copyright (c) 2001 Simon Brady 00009 // University of Otago, Dunedin, New Zealand 00010 // Reproduction rights limited as described in the COPYRIGHT file. 00011 //---------------------------------------------------------------------- 00012 // 00013 //: Asynchronous I/O wrapper 00014 // Simple wrapper around POSIX.1b asynchronous I/O (as documented in GNU Info 00015 // under Libc -> Low-Level I/O -> Asynchronous I/O). This should be portable 00016 // across most Unix-like systems. Win32 has its own async I/O facilities which 00017 // are similar to these (see Jeffrey Richter's "Advanced Windows" for details). 00018 // 00019 // An AsyncIO object represents I/O on a particular file descriptor. The read() 00020 // and write() methods attempt to initiate I/O, returning error status if 00021 // unsuccessful. If they succeed then I/O is underway and you can't touch the 00022 // buffer until completion. You can either poll by calling is_complete(), or 00023 // (better) do everything else you need to do then call wait_for_completion() 00024 // which will block in a multiprocessing-friendly way. Even if is_complete() 00025 // has returned true you must still call wait_for_completion() to determine 00026 // the completion status of the operation. 00027 // 00028 // WARNING: Although you can instantiate multiple AsyncIO objects, only one 00029 // I/O op can be in progress at once within a process. This is because we get 00030 // notified of completion by a signal, whose handler has to be a non-member 00031 // function. The handler could be extended to inspect a list of (signal, 00032 // request) pairs to determine which object's request has completed, but I 00033 // haven't done this since protecting such a list from race conditions is 00034 // probably non-trivial and I don't need the capability. Note the use of 00035 // class AsyncIO_Shared_State to clarify the distinction between shared 00036 // and per-object state. 00037 // 00038 // \verbatim 00039 // Modifications 00040 // 06-Nov-00 SJB Initial version 00041 // 13-Dec-00 SJB Use SIGIO as default completion signal 00042 // Fix up wait_for_completion, add suspend flag 00043 // \endverbatim 00044 // \author Simon Brady 00045 // \status Complete 00046 //---------------------------------------------------------------------- 00047 00048 #include <unistd.h> 00049 #ifndef _POSIX_ASYNCHRONOUS_IO 00050 #error Your system does not support POSIX asynchronous I/O 00051 #endif 00052 #include <aio.h> 00053 #include <vcl_csignal.h> 00054 #include <vcl_cstddef.h> // for size_t 00055 00056 class AsyncIO_Shared_State 00057 { 00058 protected: 00059 static volatile vcl_sig_atomic_t complete; // 0 - in progress, 1 - complete 00060 00061 // Set complete flag when completion signal arrives. Currently ignores 00062 // the signal number (see the warning at the start of this header) 00063 static void signal_handler(int); 00064 }; 00065 00066 class AsyncIO : protected AsyncIO_Shared_State 00067 { 00068 struct aiocb cb; // Control block 00069 00070 public: 00071 00072 // Constructor - perform I/O on file descriptor fd, using sig as completion 00073 // signal. Note that SIGUSR1,2 may be used by the linuxthreads library. 00074 AsyncIO(int fd, int sig = SIGIO); 00075 00076 // Destructor - disconnect signal handler 00077 ~AsyncIO(); 00078 00079 // NB: All methods returning int return zero on success, or an errno value 00080 // on failure 00081 00082 // Begin reading n bytes into buf starting at current file position 00083 int read(volatile void *buf, vcl_size_t n); 00084 00085 // Begin reading n bytes into buf starting at absolute file position pos 00086 int read(volatile void *buf, vcl_size_t n, off_t pos); 00087 00088 // Begin writing n bytes from buf starting at current file position 00089 int write(volatile void *buf, vcl_size_t nbytes); 00090 00091 // Begin writing n bytes from buf starting at absolute file position pos 00092 int write(volatile void *buf, vcl_size_t nbytes, off_t pos); 00093 00094 // Wait for I/O to complete, then return status. If suspend is true, block 00095 // the calling process while waiting, otherwise continuously poll for 00096 // completion (not recommended, but may be more reliable). 00097 int wait_for_completion(bool suspend = true); 00098 00099 // Test if operation complete. You still need to call wait_for_completion() 00100 // to tidy up and get final status 00101 bool is_complete() const { return complete; } 00102 }; 00103 00104 #endif // OTAGO_Asyncio_IO__h_INCLUDED 00105
1.7.5.1