00001
00002 #ifndef MPS_FileDescriptor_H
00003 #define MPS_FileDescriptor_H
00004
00005 #include <sys/time.h>
00006 #include <sys/types.h>
00007 #include <unistd.h>
00008
00009 #ifdef __WIN32__
00010 #include <winsock.h>
00011 #endif
00012
00013 #include <ref.h>
00014 #include <exception>
00015 #include <string>
00016 #include <vector>
00017 #include <map>
00018 #include <algorithm>
00019
00020 class FileDescriptor;
00021 class FileDescriptorManager;
00022
00023
00024
00025
00026
00027 class FileDescriptor: public Referenceable {
00028 public:
00029
00030
00031
00032
00033 class Exception: public std::exception {
00034 private:
00035 string message;
00036 int savedErrno;
00037
00038 public:
00039 Exception(string const &msg, int _savedErrno = 0)
00040 : message(msg),
00041 savedErrno(_savedErrno)
00042 {}
00043
00044 virtual char const *what() const { return message.c_str(); }
00045 int getErrno() const { return savedErrno; }
00046 };
00047
00048
00049
00050
00051 class EndOfFile: public Exception {
00052 public:
00053 EndOfFile(string const &msg)
00054 : Exception(msg)
00055 {}
00056 };
00057
00058
00059
00060
00061
00062 class Callback: public Referenceable {
00063 public:
00064
00065
00066
00067
00068 typedef void (Callback::*Method)(ref<FileDescriptor> const &desc);
00069 };
00070
00071 private:
00072 ref<FileDescriptorManager> fdMgr;
00073 int fd;
00074 char buf[1024];
00075 int buflen;
00076 int pos;
00077
00078
00079 struct callback_entry_t {
00080 ref<Callback> callback;
00081 Callback::Method callbackMethod;
00082
00083 callback_entry_t()
00084 : callback(0),
00085 callbackMethod(0)
00086 {}
00087 };
00088
00089 callback_entry_t readCallback;
00090 callback_entry_t writeCallback;
00091
00092
00093 bool fillBuffer();
00094
00095
00096 FileDescriptor(FileDescriptor const &other);
00097 FileDescriptor const &operator=(FileDescriptor const &other);
00098
00099
00100
00101
00102
00103 void updateCallbacks();
00104
00105 protected:
00106
00107
00108
00109
00110
00111
00112 virtual int lowlevel_read(int handle, char *buf, int len);
00113 virtual int lowlevel_write(int handle, char const *buf, int len);
00114 virtual int lowlevel_close(int handle);
00115
00116
00117 public:
00118
00119 FileDescriptor(ref<FileDescriptorManager> const &_fdMgr, int _fd);
00120
00121
00122 virtual ~FileDescriptor();
00123
00124 bool isOpen() const { return (fd != -1); }
00125
00126
00127 bool inputReady() {
00128 fillBuffer();
00129 return isOpen() && (pos < buflen);
00130 }
00131
00132 int getFd() const { return fd; }
00133 ref<FileDescriptorManager> const &getFdMgr() const;
00134
00135 virtual void close();
00136
00137 bool setNonBlocking(bool on);
00138
00139
00140
00141 void setReadCallback(ref<Callback> const &cb, Callback::Method cbm);
00142
00143 void setWriteCallback(ref<Callback> const &cb, Callback::Method cbm);
00144
00145
00146 void clearReadCallback();
00147
00148 void clearWriteCallback();
00149
00150 void fireReadCallback();
00151 void fireWriteCallback();
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 void block(bool forRead, bool forWrite);
00163
00164
00165
00166
00167
00168
00169
00170 int read(char *inbuf, int len, bool complete = false);
00171 int write(char const *outbuf, int len, bool complete = false);
00172
00173
00174
00175 bool read(int &ch) {
00176 if (!fillBuffer())
00177 return false;
00178 ch = buf[pos++];
00179 return true;
00180 }
00181 };
00182
00183
00184
00185
00186 class FileDescriptorManager: public Referenceable {
00187 private:
00188 typedef vector< ref<FileDescriptor> > descVec_t;
00189
00190 descVec_t allFds;
00191 int countRegistered;
00192 int maxFd;
00193 fd_set readFds;
00194 fd_set writeFds;
00195
00196
00197 friend class FileDescriptor;
00198
00199 void update(ref<FileDescriptor> const &fd, bool forRead, bool forWrite);
00200
00201 void remove(int fdnum);
00202
00203
00204 public:
00205 FileDescriptorManager();
00206
00207 void closeAll();
00208
00209
00210 int getMaxFd() const { return maxFd; }
00211 void fillFdSet(fd_set *rfds, fd_set *wfds) const;
00212 void processFdSet(fd_set *rfds, fd_set *wfds);
00213
00214
00215
00216
00217
00218
00219
00220
00221 bool poll(struct timeval const *timeout);
00222
00223
00224 void mainloop();
00225
00226
00227
00228
00229 int getCountRegistered() const { return countRegistered; }
00230
00231 };
00232
00233 #endif