From 233b1b3091282ee89cfc1c5c606f2e7cb1f36262 Mon Sep 17 00:00:00 2001 From: chatty Date: Tue, 27 Jul 1993 13:55:18 +0000 Subject: Split in 2 classes, to incorporate UchXtMultiplexer and UchTkMultiplexer --- comm/Multiplexer.cc | 239 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 145 insertions(+), 94 deletions(-) (limited to 'comm/Multiplexer.cc') diff --git a/comm/Multiplexer.cc b/comm/Multiplexer.cc index a763c6d..9f29f40 100644 --- a/comm/Multiplexer.cc +++ b/comm/Multiplexer.cc @@ -24,6 +24,7 @@ #include #include #include +#include #if defined(__hpux) && !defined(__GNUG__) #define FD_SET_TYPE(x) ((int*) x) @@ -70,7 +71,7 @@ pointed to objects for an automatic reclaim of dynamically allocated objects. /*? Create an empty channel set. ?*/ -UchMultiplexer :: UchMultiplexer () +UchBaseMultiplexer :: UchBaseMultiplexer () : Channels (new pUchChannel [NFILE]), Timers (), ReadCount (0), @@ -78,19 +79,15 @@ UchMultiplexer :: UchMultiplexer () SelectCount (0), Looping (FALSE), SigFired (FALSE), - TimeOut (-1), Handlers (new UchBaseSignalHandler* [NSIG]), NbSignals (new int [NSIG]) { - FD_ZERO (&ReadMask); - FD_ZERO (&WriteMask); - FD_ZERO (&SelectMask); memset (Handlers, 0, NSIG * sizeof (UchBaseSignalHandler*)); memset (NbSignals, 0, NSIG * sizeof (int)); } /*?nodoc?*/ -UchMultiplexer :: ~UchMultiplexer () +UchBaseMultiplexer :: ~UchBaseMultiplexer () { #ifdef CPLUS_BUG4 delete [NFILE] Channels; @@ -106,12 +103,10 @@ UchMultiplexer :: ~UchMultiplexer () Add a channel to the set. Note that the argument is a pointer to the channel; no copy is made by this function. If a channel with the same file descriptor as the one being added is already in the set, -the old channel is first removed, thus calling \fun{RemoveNotify} for that channel. -The virtual function \fun{AddNotify} is called before actually adding the channel -to the set. +the old channel is first removed. ?*/ void -UchMultiplexer :: Add (UchChannel* chan) +UchBaseMultiplexer :: Add (UchChannel* chan) { int fd = chan->FilDes (); if (fd < 0) @@ -119,8 +114,7 @@ UchMultiplexer :: Add (UchChannel* chan) pUchChannel ochan = Channels [fd]; if (ochan) Remove (fd); - chan->AddNotify (*this); - AddNotify (chan); + chan->Added (*this); Channels [fd] = chan; SetMasks (fd, chan->IOMode ()); } @@ -129,18 +123,15 @@ pUchChannel NIL_CHAN (0); /*? Remove a channel from the set. -The virtual function \fun{RemoveNotify} is called before actually removing the channel -from the set. ?*/ void -UchMultiplexer :: Remove (int fd) +UchBaseMultiplexer :: Remove (int fd) { if (fd < 0) return; UchChannel* ch = Channels [fd]; if (ch) { - ch->RemoveNotify (*this); - RemoveNotify (ch); + ch->Removed (*this); SetMasks (fd, IONone); Channels [fd] = 0; } @@ -152,7 +143,7 @@ This function calls \fun{Remove} for all channels of the set. This is a way of exiting from \fun{LoopScan}. ?*/ void -UchMultiplexer :: RemoveAll () +UchBaseMultiplexer :: RemoveAll () { for (int fd = 0; fd < NFILE; fd++) Remove (fd); @@ -161,20 +152,124 @@ UchMultiplexer :: RemoveAll () /*? Change the mode of a channel in the set. Mode \var{IONone} makes the channel inactive (without removing it). -The virtual function \fun{SetModeNotify} is called before actually changing -the mode of the channel. ?*/ void -UchMultiplexer :: SetMode (int fd, IOMODE mode) +UchBaseMultiplexer :: SetMode (int fd, IOMODE mode) { if (fd < 0) return; - SetModeNotify (Channels [fd], mode); SetMasks (fd, mode); Channels [fd] -> SetMode (mode); } +#ifdef DOC + +/*? +This array operator returns a (smart) pointer to the channel corresponding to file descriptor \var{fd}. +If there is no such channel in this channel set, the operator returns NIL. +?*/ +pUchChannel +UchBaseMultiplexer :: operator [] (int fd) +{ } + +/*? +Add a channel to the set. +Here the argument is a reference, and a dynamically allocated copy of it is actually added. +Compare with previous function. +?*/ +void +UchBaseMultiplexer :: Add (const UchChannel& ch) +{ } + +#endif /* DOC */ + +/*! +This function is called by UchSignalHandlers when a signal is +received. It just stores the signal for future (and safe) handling. +!*/ +/*?hidden?*/ +void +UchBaseMultiplexer :: HandleSignal (UchBaseSignalHandler& h) +{ + if (!SigFired) + AddSignalHook (); + SigFired = TRUE; + int sig = h.GetSignal () - 1; + /* We have to work with arrays, because we are in a signal + handler, and we cannot use lists */ + Handlers [sig] = &h; + NbSignals [sig]++; + +} + + +void +UchBaseMultiplexer :: AddSignalHook () +{ +} + +void +UchBaseMultiplexer :: HandleDeferredSignals () +{ + CcuSignalBlocker b (AllSigs); + int c; + for (int i = 0; i < NSIG; ++i) + if (c = NbSignals [i]) { + Handlers [i]->DeferredHandle (c); + NbSignals [i] = 0; + Handlers [i] = 0; + } +} + +static jmp_buf reset_run; + +class UchMpxAborter : public UchBaseSignalHandler { +public: + UchMpxAborter (UchBaseMultiplexer& m, int s) : UchBaseSignalHandler (m, s) {} + void DeferredHandle (int) { MyMpx.Abort (); } +}; + +MPX_RES +UchBaseMultiplexer :: Run () +{ + if (setjmp (reset_run)) + return isMpxAborted; + + UchMpxAborter h1 (*this, SigTerm); + UchMpxAborter h2 (*this, SigInt); + + return Loop (); +} + +void +UchBaseMultiplexer :: Abort () +{ + if (Looping) + longjmp (reset_run, 1); +} + +void +UchBaseMultiplexer :: Close () +{ + RemoveAll (); + Looping = FALSE; +} + +UchMultiplexer :: UchMultiplexer () +: UchBaseMultiplexer (), + TimeOut (-1) +{ + FD_ZERO (&ReadMask); + FD_ZERO (&WriteMask); + FD_ZERO (&SelectMask); +} + +UchMultiplexer :: ~UchMultiplexer () +{ +} + + // update the masks when channel fd changes its mode // @@ -220,20 +315,6 @@ UchMultiplexer :: SetMasks (int fd, IOMODE mode) } -/*?nextdoc?*/ -void -UchMultiplexer :: AddNotify (UchChannel*) -{ - // nothing -} - -/*?nextdoc?*/ -void -UchMultiplexer :: RemoveNotify (UchChannel*) -{ - // nothing -} - /*? This function calls the select handler of each channel of the set in select mode. It returns TRUE as soon as one select handler returns true, @@ -258,19 +339,6 @@ UchMultiplexer :: HandleSelect () return FALSE; } -/*? -These virtual functions are called by the functions \fun{Add}, \fun{Remove} -(and thus \fun{RemoveAll}) and \fun{SetMode}. -They provide hooks for application that need to take special action when the -set changes. They are called before the corresponding action is actually -carried out. -By default these functions do nothing. -?*/ -void -UchMultiplexer :: SetModeNotify (UchChannel*, IOMODE) -{ - // nothing -} ////// should add signal handling /*?nextdoc?*/ @@ -366,11 +434,11 @@ an error occurs, the channel set has no more active channel This can occur because the select, read or write handler of a channel may remove the channel or change its mode. This is usually done when the read handler detects an end of file. -\fun{LoopScan} returns 0 when there are no more active channel in the set, -it returns -1 when an error occured (the code is in \var{errno}), -and it returns 1 if \fun{LoopEnd} was called. +\fun{LoopScan} returns \var{isMpxEmpty} when there are no more active channel in the set, +it returns \var{isMpxError} when an error occured (the code is in \var{errno}), +and it returns \var{isMpxTerminated} if \fun{LoopEnd} or \fun{Close} was called. ?*/ -int +MPX_RES UchMultiplexer :: LoopScan (bool nointr) { fd_set rmsk, wmsk; @@ -378,24 +446,17 @@ UchMultiplexer :: LoopScan (bool nointr) Looping = TRUE; for (fd0 = 0; Looping; fd0 < NFILE ? fd0++ : (fd0 = 0)) { + /* First, handle signals */ - if (SigFired) { - CcuSignalBlocker b (AllSigs); - int c; - for (int i = 0; i < NSIG; ++i) - if (c = NbSignals [i]) { - Handlers [i]->DeferredHandle (c); - NbSignals [i] = 0; - Handlers [i] = 0; - } - } + if (SigFired) + HandleDeferredSignals (); /* Then, timers */ CcuCoreTimer::Fire (&Timers); /* Then, I/Os */ if (ReadCount == 0 && WriteCount == 0 && SelectCount == 0) - return 0; + return isMpxEmpty; for (fd = fd0, nfd = SelectCount; nfd; (fd < NFILE) ? fd++ : (fd = 0)) { if (! FD_ISSET (fd, &SelectMask)) @@ -405,7 +466,7 @@ UchMultiplexer :: LoopScan (bool nointr) break; nfd--; if (! Looping) - return 1; + return isMpxTerminated; } if (nfd) // a handler returned TRUE. continue; @@ -425,7 +486,7 @@ UchMultiplexer :: LoopScan (bool nointr) if (nfd < 0) { if (nointr && nfd == -1 && errno == EINTR) continue; - return nfd; + return isMpxError; } for (fd = fd0; nfd; (fd < NFILE) ? fd++ : (fd = 0)) { @@ -433,17 +494,17 @@ UchMultiplexer :: LoopScan (bool nointr) nfd--; Channels [fd] -> HandleWrite (); if (! Looping) - return 1; + return isMpxTerminated; } if (FD_ISSET (fd, &rmsk)) { nfd--; Channels [fd] -> HandleRead (); if (! Looping) - return 1; + return isMpxTerminated; } } } - return 1; + return isMpxTerminated; } // string repr @@ -458,24 +519,6 @@ UchMultiplexer :: StrRepr (char* buf) #ifdef DOC // fake entries for inline functions - -/*? -This array operator returns a (smart) pointer to the channel corresponding to file descriptor \var{fd}. -If there is no such channel in this channel set, the operator returns NIL. -?*/ -pUchChannel -UchMultiplexer :: operator [] (int fd) -{ } - -/*? -Add a channel to the set. -Here the argument is a reference, and a dynamically allocated copy of it is actually added. -Compare with previous function. -?*/ -void -UchMultiplexer :: Add (const UchChannel& ch) -{ } - /*? This function makes \fun{LoopScan} exit immediately. Thus it must be called from within a channel's handler. @@ -487,12 +530,20 @@ UchMultiplexer :: LoopEnd () #endif /* DOC */ void -UchMultiplexer :: RegisterSignal (UchBaseSignalHandler& h) +UchMultiplexer :: SetTimeOut (Millisecond delay) { - SigFired = TRUE; - int sig = h.GetSignal () - 1; - /* We have to work with arrays, because we are in a signal - handler, and we cannot use lists */ - Handlers [sig] = &h; - NbSignals [sig]++; + CcuTimeStamp now; + TimeOut = now + delay; +} + +void +UchMultiplexer :: SuppressTimeOut () +{ + TimeOut = -1; +} + +MPX_RES +UchMultiplexer :: Loop () +{ + return LoopScan (); } -- cgit v1.1