📄 io.h
字号:
/*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************//** * Copyright (c) 2000 * * A C++ implementation of Asynchronous Input/Output, using threaded * objects to handle the data. * */#ifndef THREADS_ASYNC_IO#define THREADS_ASYNC_IO#include <threads/socket.h>#include <list>#include <string>#include <cstdio>#include <cstdarg>#include <ctime>extern "C" {# include <sys/time.h>};namespace cpp_threads { class IOBuffer; class PthreadIO; /** * Descriptor sets, are usually C macros with * limited manipulation ability. * * This class provides file descriptor sets, with all * the same manipulations as in the defined C macros, * while also simplifying the use of descriptor sets * in a C++ environment, and mainly use with Socket * classes. See thread_io for more deatiled information * about this, and how to use this class. In reality * this is merely a list of Sockets, that are also contained * in a descriptor set. */ class DescriptorSet : public std::list<Socket *> { public: typedef std::list<Socket*>::iterator iterator; protected: fd_set _set; public: DescriptorSet(); ~DescriptorSet(); /** * Delete all contents of the descriptor set, including all * Sockets that are in the list. The Sockets themselves are * not destroyed, merely their copies deleted from the list. */ void zero(); /** * Add a Socket to the list and descriptor set. * * @param sd A pointer to a Socket to add. */ void add(Socket*); /** * Remove a given Socket from the descriptor set/list, * that is equal to the Socket given as parameter. The * Socket is removed from the descriptor and list, but * not destroyed, merely its copy removed. * * @param sd The Socket, wich needs to be removed. */ void del(Socket&); /** * Check wether a given socket is set, inside the descriptor * set. This is useful, when a descriptor has been passed * through select, and to check weather a given socket is * available or not. * * @param sd An address of a socket to check. */ bool isSet(Socket&); /** * If this class is passed as a fd_set parameter, make sure * the correct data is passed. * * @return File descriptor set in the class. */ operator fd_set *(); /** * The same as above, but if the the descriptor set is referenced * then make sure it is directly and correctly accessed. * * @return Reference to the file descriptor set. */ operator fd_set(); /** * This is a copy constructor, that will copy the data * from another descriptor set, and make this class a direct * copy of the other. */ DescriptorSet& operator =(DescriptorSet&); }; /** * Buffered socket * * This is a base class, to allow for buffered sockets. In an * environment, where many sockets are present, it may be necessary * to keep each socket with separate input buffers, which is what * this class does. * * When a thread receives an interrupt, which says data is available, * then this is the class that provides the data. It has an * associated IO buffer, which contains the inputted data. At * current, only the input is buffered. * * @author Orn E. Hansen <oe.hansen@gamma.telenordia.se> * @short Superclass for buffered sockets. */ class SocketBuffer : public Socket { protected: IOBuffer* _in_buf; IOBuffer* _out_buf; public: SocketBuffer(); SocketBuffer(int); SocketBuffer(Socket&); SocketBuffer(SocketBuffer&); virtual ~SocketBuffer(); /** * Static method, provided as means to turn an open * socket into a buffered socket. The socket remains the * same, and a buffer is associated with it. * * @return New socket buffer. */ static SocketBuffer* wrapSocket(Socket&); /** * This method differs from the one above, in that it * accepts a pointer to a socket, instead of a reference. It * deletes this pointer, after having wrapped a buffer around * it. * * @return New socket buffer. */ static SocketBuffer* wrapSocket(Socket*); /** * This method provides means to obtain the buffer * that is associated with input, for this socket. * * @return IO Buffer. */ IOBuffer& inputBuf(); /** * This method provides means to obtain the buffer * that is associated with output, for this socket. * * @return IO Buffer. */ IOBuffer& outputBuf(); /** * An operator, that provides the same effect as the * above, but proves handy when passing this class to * methods and functions. * * @return IO Buffer */ operator IOBuffer& (); /** * Similar to above, but provides means to obtain the * pointer to the io buffer, instead of a reference to * it. * * @return IO Buffer pointer. */ operator IOBuffer* (); }; /** * This class provides a basic superclass for all * classes, that are to receive asynchronous input * from a managing class. * * @author Orn E. Hansen <oe.hansen@gamma.telenordia.se> * @short Superclass to asynchronous input classes. */ class AsynchronousIO : public Mutex { public: /** Full duplex and half duplex? * * In general, there are two processes running. The * application process, and the IO manager process. In * full duplex mode, the IO manager will interrupt the * application process and deliver it there. Another * possibility in full duplex mode, is to *merely* interrupt * the application process, and not to call the 'got' * routine, but leave that to the application. */ enum async_type_t { /** Deliver control to the got() here, as application process. */ dupl_deliver_e, /** Signal application only, when data is ready. */ dupl_signal_e, /** Deliver data to got, but as the IO manager process. */ dupl_half_e }; private: /** For internal use only. Signalling system. */ void* _ssyst; /** * This is an indirect jump to the above routines. It makes it * possible to call them asynchronously. If the two parameters are * omitted, an exception call will be made, otherwise the parameters * will be understood as a pointer to data, and its length. * * @param l Length of the data, -1 means it is an exception. */ void jump(SocketBuffer* p=0,int n=-1); void signalIOReady(void*); protected: int _pid; SocketBuffer _fd; SocketBuffer* _client; async_type_t _mode; /** * All IO that comes in through any file descriptors associated * with this class, are sent to this method. Wether the class is * handling a simple file or serial IO, or if it is a server socket * input is channeled through this method. * * This method must be rewritten, in a derived class. * * @param f Reference to the buffered socket. * */ virtual void got(SocketBuffer&) = 0; /** * It is also possible to receive IO exceptions, with this * class. Those exceptions will be channeled through the following * method. */ virtual void exception(SocketBuffer&); /** * This method, does what is necessary to save the buffer for * later recall. It is called, when this class is locked and * cannot be called again. This can happen, when the handler * is already in a call (interrupt), and has not opened up * for further calls (call unlock for this). * * @param s The socket buffer, that needs attention. */ virtual void queueSocket(SocketBuffer *); /** * This is the method each client uses to catch the close() * on the socket. It is called just prior to the socket being * closed, and allows the client to perform any necessary data * before the close happens. * */ virtual void close(Socket&); /** * Urgent interrupt. * * This method, is called whenever the thread receives a signal * urgent interrupt. * * The signal is used internally, to indicate that asynchronous * delivery has finished. Derived classes will put their own * code in here, to handle the situation and other urgent * situations that may occur. */ virtual void signalUrgent(void *); friend class cpp_threads::PthreadIO; public: AsynchronousIO(async_type_t); virtual ~AsynchronousIO(); /** * This method provides means for other threads to obtain * the file descriptor that this class is managing. * * @return File descriptor the class manages. */ SocketBuffer& fd(); /** * In case of server socket, a client is sending us data. * The routine handling the input, may request here the file * descriptor of the client. The return value is a valid * file descriptor, or a -1 if no client input is in process, * which would indicate an internal error. * * @return Socket of the client being processed. */ SocketBuffer& clientFD(); }; /** * This class provides the means for a program to have * asynchronous IO at their fingertips. * * Each IO device, that desires asynchronous handling, * declares itself as a subclass to this class. And * provides the file descriptor handle to manage. The * class will then use the thread to wait for IO on the * handle and give the data read to the * @ref #got * method and data that needs to be sent, can be sent * through the various put methods. * * The @ref #thread_io class is well suited for writing * clients, that need to be launched from a simple application * that needs to maintain certain user display, and receive * data in the background. This class will take care of * data reception, and delivery relieving the main application * of having to be blocked during IO operations. The class * can also take care of small and medium sized server
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -