00001 #ifndef _STR_StreamFDModule_H_ //-*-c++-*-
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef __GNUG__
00022 # pragma interface
00023 #endif
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <cstddef>
00033
00034 #include <UniEvent/EventPtr.h>
00035 #include <UniEvent/EventPtrT.h>
00036 #include <UniEvent/UnixEventRegistry.h>
00037 #include <UniEvent/UNIXError.h>
00038
00039 #ifndef _STR_StreamModule_H_
00040 # include <StrMod/StreamModule.h>
00041 #endif
00042 #ifndef _STR_StrChunkPtr_H_
00043 # include <StrMod/StrChunkPtr.h>
00044 #endif
00045
00046 #define _STR_StreamFDModule_H_
00047
00048 template <class enum_t, enum_t first, enum_t last> class enum_set;
00049
00050 namespace strmod {
00051 namespace strmod {
00052
00053 class GroupVector;
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 class StreamFDModule : public StreamModule
00067 {
00068 protected:
00069 class FPlug;
00070 friend class FPlug;
00071 private:
00072 class BufferList;
00073 class EvMixin;
00074 friend class StreamFDModule::EvMixin;
00075 class FDPollRdEv;
00076 friend class StreamFDModule::FDPollRdEv;
00077 class FDPollWrEv;
00078 friend class StreamFDModule::FDPollWrEv;
00079 class FDPollErEv;
00080 friend class StreamFDModule::FDPollErEv;
00081 class ResumeReadEv;
00082 friend class StreamFDModule::ResumeReadEv;
00083 class ResumeWriteEv;
00084 friend class StreamFDModule::ResumeWriteEv;
00085
00086 public:
00087
00088
00089
00090
00091 enum IOCheckFlags {
00092 CheckNone,
00093 CheckRead,
00094 CheckWrite,
00095 CheckBoth
00096 };
00097
00098
00099 enum ErrorType {
00100 ErrRead,
00101 ErrWrite,
00102 ErrGeneral,
00103 ErrFatal
00104 };
00105
00106 typedef lcore::enum_set<ErrorType, ErrRead, ErrFatal> ErrorSet;
00107
00108
00109 static const STR_ClassIdent identifier;
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 static const size_t S_max_bytes_without_dispatch = 256U * 1024U;
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 StreamFDModule(int fd,
00143 unievent::Dispatcher &disp,
00144 unievent::UnixEventRegistry &ureg,
00145 IOCheckFlags checkmask = CheckBoth);
00146
00147 virtual ~StreamFDModule();
00148
00149 inline virtual int AreYouA(const lcore::ClassIdent &cid) const;
00150
00151 inline virtual bool canCreate(int side) const;
00152 inline virtual bool ownsPlug(const Plug *p) const;
00153 inline virtual bool deletePlug(Plug *p);
00154
00155
00156 bool hasErrorIn(ErrorType err) const throw ();
00157
00158 bool hasErrorIn(const ErrorSet &set) const throw ();
00159
00160
00161
00162
00163
00164 void onErrorIn(ErrorType err, const unievent::EventPtr &ev) throw();
00165
00166
00167
00168 void resetErrorIn(ErrorType err) throw ();
00169
00170 const unievent::UNIXError &getErrorIn(ErrorType err) const throw ();
00171
00172
00173 inline void setSendChunkOnEOF(bool newval) throw();
00174
00175 inline bool getSendChunkOnEOF() throw() { return flags_.chunkeof; }
00176
00177
00178 inline void setMaxChunkSize(size_t mbs);
00179
00180 size_t getMaxChunkSize() const { return(max_block_size_); }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 size_t getBestChunkSize() const;
00191
00192
00193
00194
00195
00196
00197 inline void setMaxToBest();
00198
00199
00200 protected:
00201 class MyPollEvent;
00202 friend class MyPollEvent;
00203
00204 class FPlug : public Plug {
00205 friend class StreamFDModule;
00206 public:
00207 static const STR_ClassIdent identifier;
00208
00209
00210 FPlug(StreamFDModule &parent) : Plug(parent) { }
00211 virtual ~FPlug() { }
00212
00213
00214 inline virtual int AreYouA(const lcore::ClassIdent &cid) const;
00215
00216
00217 inline StreamFDModule &getParent() const;
00218
00219
00220 virtual int side() const { return(0); }
00221
00222 protected:
00223
00224 virtual const lcore::ClassIdent *i_GetIdent() const {
00225 return &identifier;
00226 }
00227
00228
00229 inline virtual const StrChunkPtr i_Read();
00230
00231 inline virtual void i_Write(const StrChunkPtr &ptr);
00232 };
00233
00234 virtual const lcore::ClassIdent *i_GetIdent() const { return &identifier; }
00235
00236 inline virtual Plug *i_MakePlug(int side);
00237
00238
00239 virtual void plugWrite(const StrChunkPtr &ptr);
00240
00241 virtual const StrChunkPtr plugRead();
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 virtual void doReadFD();
00253
00254
00255
00256
00257
00258
00259
00260 virtual void doWriteFD();
00261
00262
00263
00264
00265
00266
00267
00268 virtual void writeEOF();
00269
00270
00271 void setErrorIn(ErrorType err, const unievent::UNIXError &errval);
00272
00273
00274 void eventRead();
00275
00276 void eventWrite();
00277
00278 void eventError();
00279
00280 void eventResumeRead();
00281
00282 void eventResumeWrite();
00283
00284
00285 int getFD() const throw() { return fd_; }
00286
00287 private:
00288 struct ErrorInfo;
00289
00290 int fd_;
00291 struct {
00292 unsigned int plugmade : 1;
00293 unsigned int checkingrd : 1;
00294 unsigned int checkingwr : 1;
00295 unsigned int readeof : 1;
00296 unsigned int eofwritten : 1;
00297 unsigned int chunkeof : 1;
00298 } flags_;
00299
00300 FPlug plug_;
00301 StrChunkPtr buffed_read_;
00302 StrChunkPtr cur_write_;
00303 BufferList &curbuflist_;
00304 unsigned int max_block_size_;
00305 unsigned int read_since_read_posted_;
00306 unsigned int written_since_write_posted_;
00307
00308 EvMixin *parenttrackers_[5];
00309
00310
00311 typedef unievent::EventPtr EventPtr;
00312 EventPtr readev_;
00313 EventPtr writeev_;
00314 EventPtr errorev_;
00315 unievent::EventPtr resumeread_;
00316 unievent::EventPtr resumewrite_;
00317 ErrorInfo &errorinfo_;
00318 unievent::Dispatcher &disp_;
00319 unievent::UnixEventRegistry &ureg_;
00320 };
00321
00322
00323
00324 inline int StreamFDModule::AreYouA(const lcore::ClassIdent &cid) const
00325 {
00326 return((identifier == cid) || StreamModule::AreYouA(cid));
00327 }
00328
00329 inline bool StreamFDModule::canCreate(int side) const
00330 {
00331 return (side == 0 && !flags_.plugmade);
00332 }
00333
00334 inline bool StreamFDModule::ownsPlug(const Plug *p) const
00335 {
00336 return(flags_.plugmade && (p == &plug_));
00337 }
00338
00339 inline bool StreamFDModule::deletePlug(Plug *p)
00340 {
00341 if (ownsPlug(p)) {
00342 flags_.plugmade = 0;
00343 return(true);
00344 } else
00345 return(false);
00346 }
00347
00348 inline void StreamFDModule::setSendChunkOnEOF(bool newval) throw()
00349 {
00350 flags_.chunkeof = newval;
00351 }
00352
00353 inline void StreamFDModule::setMaxChunkSize(size_t mbs)
00354 {
00355 assert(mbs > 0);
00356
00357 if (mbs > 0)
00358 {
00359 max_block_size_ = mbs;
00360 }
00361 }
00362
00363 inline void StreamFDModule::setMaxToBest()
00364 {
00365 setMaxChunkSize(getBestChunkSize());
00366 }
00367
00368 inline StreamModule::Plug *StreamFDModule::i_MakePlug(int side)
00369 {
00370 if (canCreate(side))
00371 {
00372 flags_.plugmade = 1;
00373 return(&plug_);
00374 }
00375 else
00376 {
00377 return(0);
00378 }
00379 }
00380
00381
00382
00383 inline int StreamFDModule::FPlug::AreYouA(const lcore::ClassIdent &cid) const
00384 {
00385 return((identifier == cid) || Plug::AreYouA(cid));
00386 }
00387
00388 inline StreamFDModule &StreamFDModule::FPlug::getParent() const
00389 {
00390 return(static_cast<StreamFDModule &>(Plug::getParent()));
00391 }
00392
00393 inline const StrChunkPtr StreamFDModule::FPlug::i_Read()
00394 {
00395 return(getParent().plugRead());
00396 }
00397
00398 inline void StreamFDModule::FPlug::i_Write(const StrChunkPtr &ptr)
00399 {
00400 getParent().plugWrite(ptr);
00401 }
00402
00403 }
00404 }
00405
00406 #endif