summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchatty2000-11-28 17:07:44 +0000
committerchatty2000-11-28 17:07:44 +0000
commit914fe0ed606bdfbcafc9fe74596bbe7fe09a8e68 (patch)
tree26ec9361118432f34e9ec047635675125b5cabd5
parentc34b4aa9b8af7b4a0c98e7a6760fdb5f7370074a (diff)
downloadivy-league-914fe0ed606bdfbcafc9fe74596bbe7fe09a8e68.zip
ivy-league-914fe0ed606bdfbcafc9fe74596bbe7fe09a8e68.tar.gz
ivy-league-914fe0ed606bdfbcafc9fe74596bbe7fe09a8e68.tar.bz2
ivy-league-914fe0ed606bdfbcafc9fe74596bbe7fe09a8e68.tar.xz
* Meilleures verifications de NFILE, en attendant mieux
-rw-r--r--comm/Multiplexer.cc143
1 files changed, 93 insertions, 50 deletions
diff --git a/comm/Multiplexer.cc b/comm/Multiplexer.cc
index 1edb225..b879ce6 100644
--- a/comm/Multiplexer.cc
+++ b/comm/Multiplexer.cc
@@ -3,7 +3,7 @@
*
* by Michel Beaudouin-Lafon
*
- * Copyright 1990-1996
+ * Copyright 1990-1997
* Laboratoire de Recherche en Informatique (LRI)
*
* Channel sets, or multiplexers
@@ -13,8 +13,8 @@
*/
#include "Multiplexer.h"
-#include "../UCH/TimeOut.h"
-#include "../UCH/SignalHandler.h"
+#include "TimeOut.h"
+#include "SignalHandler.h"
#include <signal.h> // for NSIG
#include <sys/errno.h>
@@ -36,7 +36,9 @@
extern "C" int select (int, fd_set*, fd_set*, fd_set*, struct timeval*);
#endif
-extern int errno;
+extern int errno;
+
+UchBaseMultiplexer* UchMpx = 0;
#ifndef FD_SET
#ifndef NFDBITS
@@ -62,7 +64,7 @@ interruption-based) timers and signal handlers.
Some of the channels in the set are active, others can be inactive. A
multiplexer can be scanned so that the functions \fun{HandleRead} and
\fun{HandleWrite} are called for every active channel that is ready to
-read or write.
+read or write.
If a channel needs to perform a background task or buffer input/output,
it can add a hook on the multiplexer with \fun{AddHook} which will be
@@ -83,11 +85,12 @@ implementation of multiplexers.
Note that the functions that take an integer file descriptor as
argument can be passed a \typ{FILDES} or a \typ{UchChannel} because
-the corresponding conversion operators are defined.
+the corresponding conversion operators are defined.
+
+The way to Add/Remove a channel from a multiplexer is to call
+\fun{Add} and \fun{Remove} of the channel with the multiplexer as an
+argument for the first one.
-The semantic to Add/Remove a channel from a multiplexer is to call
-\fun{Add} and \fun{Remove} of the channel with the multiplexer as
-an argument for the first one.
?*/
/*?
@@ -124,6 +127,7 @@ UchBaseMultiplexer :: ~UchBaseMultiplexer ()
Channels = 0;
}
+
/*?
This array operator returns a pointer to the channel corresponding to file descriptor \var{fd}.
If there is no such channel in this channel set, the operator returns NIL.
@@ -134,18 +138,18 @@ UchBaseMultiplexer :: operator [] (int fd)
return (fd < 0 || fd >= NFILE) ? 0 : Channels [fd];
}
-/*?
-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. That means that for a given file descriptor,
-there can be only one channel working on it at a time.
+/*?
+Add a channel to the multiplexer. 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. That
+means that for a given file descriptor, there can be only one channel
+working on it at a time.
?*/
bool
UchBaseMultiplexer :: Add (UchChannel* chan)
{
int fd = chan->FilDes ();
- if (fd < 0)
+ if (fd < 0 || fd >= NFILE)
return false;
UchChannel* ochan = Channels [fd];
if (ochan)
@@ -162,7 +166,7 @@ Remove a channel from the set. This function can be passed a \var{UchChannel}.
bool
UchBaseMultiplexer :: Remove (int fd)
{
- if (fd < 0)
+ if (fd < 0 || fd >= NFILE)
return false;
UchChannel* ch = Channels [fd];
if (ch) {
@@ -262,7 +266,6 @@ UchBaseMultiplexer :: SetMasks (int, IOMODE)
{
}
-#if 0
static jmp_buf reset_run;
class UchMpxAborter : public UchBaseSignalHandler {
@@ -270,7 +273,6 @@ public:
UchMpxAborter (UchBaseMultiplexer& m, int s) : UchBaseSignalHandler (m, s) {}
void DeferredHandle (int) { MyMpx.Abort (); }
};
-#endif
/*?
Run a multiplexer: make it repeatedly scan its channels, and take the
@@ -288,17 +290,15 @@ or signals SIGINT or SIGTERM were received.\\
MPX_RES
UchBaseMultiplexer :: Run ()
{
-#if 0
if (setjmp (reset_run))
return isMpxAborted;
UchMpxAborter h1 (*this, SigTerm);
UchMpxAborter h2 (*this, SigInt);
-#endif
+
return Loop ();
}
-#if 0
/*?
Remove all channels from the multiplexer, thus stopping it if running.
?*/
@@ -318,7 +318,6 @@ UchBaseMultiplexer :: Abort ()
if (Looping)
longjmp (reset_run, 1);
}
-#endif
/*?class UchMultiplexer
The class \typ{UchMultiplexer} is the default implementation of multiplexers,
@@ -334,6 +333,7 @@ UchMultiplexer :: UchMultiplexer ()
TimeOut (-1),
Looping (false),
Hooks ()
+
{
FD_ZERO (&ReadMask);
FD_ZERO (&WriteMask);
@@ -391,11 +391,36 @@ UchMultiplexer :: SetMasks (int fd, IOMODE mode)
}
-#ifdef 0
-Scan n'est plus a jour avec LoopScan et n'est jamais appelee de
-toutes facons....
+#if 0
+/*?
+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,
+else it returns false when the select handlers have been called.
+?*/
+bool
+UchMultiplexer :: HandleSelect ()
+{
+ int fd, nfd;
+
+ if (fd0 >= NFILE)
+ fd0 = 0;
+ for (fd = fd0++, nfd = SelectCount; nfd; (fd < NFILE) ? fd++ : (fd = 0)) {
+ if (! FD_ISSET (fd, &SelectMask))
+ continue;
+ if (Channels [fd] -> HandleSelect ())
+ return true;
+ nfd--;
+ if (! Looping)
+ return false;
+ }
+ return false;
+}
+
+#endif
////// should add signal handling
+////// Hooks are probably badly handled
+////// Scan should disappear anyway. Only use is in Xtv.
/*?nextdoc?*/
int
UchMultiplexer :: Scan (bool nointr, bool poll)
@@ -403,28 +428,20 @@ UchMultiplexer :: Scan (bool nointr, bool poll)
fd_set rmsk, wmsk;
int nfd, ret = -1;
register int fd;
- struct timeval tout;
+ struct timeval tv;
struct timeval* timeout = 0;
if (poll) {
- timeout = &tout;
- tout.tv_sec = tout.tv_usec = 0;
+ timeout = &tv;
+ tv.tv_sec = tv.tv_usec = 0;
}
while (ret <= 0) {
- if (ReadCount == 0 && WriteCount == 0 && SelectCount == 0)
+ if (ReadCount == 0 && WriteCount == 0 && SelectCount == 0) {
+ ExecHooks (true);
return 0;
-
-/* Old version with HandleSelect, to be replaced by Hooks
- for (fd = 0, nfd = SelectCount; nfd; fd++) {
- if (! FD_ISSET (fd, &SelectMask))
- continue;
- UchChannel* ch = Channels [fd];
- if (ch && ch->HandleSelect ())
- return -2;
- nfd--;
}
-*/
+ ExecHooks (false);
rmsk = ReadMask;
wmsk = WriteMask;
@@ -437,9 +454,9 @@ UchMultiplexer :: Scan (bool nointr, bool poll)
/* if delay < 0, select is unhappy */
if (delay < 0)
ret = 0;
- tout.tv_sec = delay / 1000;
- tout.tv_usec = 1000 * (delay % 1000);
- timeout = &tout;
+ tv.tv_sec = delay / 1000;
+ tv.tv_usec = 1000 * (delay % 1000);
+ timeout = &tv;
}
/* skipping select is a trick to avoid problems with timers. However,
@@ -447,9 +464,11 @@ UchMultiplexer :: Scan (bool nointr, bool poll)
- manage priorities (I'm not sure the current situation is sound)
- handle situations when we are late.
*/
+ /* Call select, except if late with timers */
if (ret != 0)
ret = select (NFILE, FD_SET_TYPE(&rmsk), FD_SET_TYPE(&wmsk), 0, timeout);
+ /* Handle time out */
if (ret == 0) {
if (TimeOut != -1)
/* Fire might be called without reason if polling is on. Too bad... */
@@ -457,17 +476,23 @@ UchMultiplexer :: Scan (bool nointr, bool poll)
else if (!poll)
fprintf (stderr, "select returned 0 without reason!\n");
return 0;
+
+ /* Handle errors */
} else if (ret < 0) {
- if (nointr && errno == EINTR)
+ if (nointr && ret == -1 && errno == EINTR)
continue;
- else
+ else {
+ ExecHooks (true);
return ret;
+ }
}
}
-
+
+
+ /* Finally, handle pending input and output */
for (fd = 0, nfd = ret; nfd; fd++) {
if (FD_ISSET (fd, &wmsk)) {
- nfd --;
+ nfd--;
UchChannel* ch = Channels [fd];
if (ch)
ch->HandleWrite ();
@@ -483,7 +508,6 @@ UchMultiplexer :: Scan (bool nointr, bool poll)
return ret;
}
-#endif /* Scan */
/*?
Scan the channels in the set and call the channel's handlers.
@@ -502,14 +526,14 @@ If \var{poll} is true, the call is non-blocking, else it is blocking.
\fun{Scan} calls \fun{select} only once;
it returns -2 if a select handler returns, it returns 0 if the channel set has no active channels,
else it returns the return code of \fun{select}.
-\fun{LoopScan} calls \fun{select} repeatedly until \var{LoopEnd} is called, or
+\fun{LoopScan} calls \fun{select} repeatedly until \var{Stop} is called, or
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 \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.
+and it returns \var{isMpxTerminated} if \fun{Stop} or \fun{Close} was called.
?*/
MPX_RES
UchMultiplexer :: LoopScan (bool nointr)
@@ -630,6 +654,7 @@ UchMultiplexer :: Loop ()
return LoopScan ();
}
+
void
UchMultiplexer :: Stop ()
{
@@ -677,3 +702,21 @@ UchMultiplexer :: ExecHooks (bool final)
}
}
+void
+UchOpen (UchBaseMultiplexer* m)
+{
+ UchMpx = m ? m : new UchMultiplexer;
+ DnnMpx = UchMpx;
+}
+
+MPX_RES
+UchLoop ()
+{
+ return UchMpx->Loop ();
+}
+
+void
+UchStop ()
+{
+ UchMpx->Stop ();
+}