summaryrefslogtreecommitdiff
path: root/comm/Multiplexer.cc
diff options
context:
space:
mode:
authorsc2000-11-28 17:07:47 +0000
committersc2000-11-28 17:07:47 +0000
commitee937667fd0ecd82faab4c88d756b906fb625f1a (patch)
tree19e679318b5cb87e8be1a05a7bbc9ba5568d0814 /comm/Multiplexer.cc
parent1326b11d65f7020f5f6c691305d2c090b064bd04 (diff)
downloadivy-league-ee937667fd0ecd82faab4c88d756b906fb625f1a.zip
ivy-league-ee937667fd0ecd82faab4c88d756b906fb625f1a.tar.gz
ivy-league-ee937667fd0ecd82faab4c88d756b906fb625f1a.tar.bz2
ivy-league-ee937667fd0ecd82faab4c88d756b906fb625f1a.tar.xz
Integration into IvyLeague
Uvh -> Ivl Multiplexer.* is renamed into Scheduler.* A few name conflicts in the merger with ex-DNN have been solved Imakefile is replaced by Makefile Created InetAddress.* and UnixAddress.* from Address.* Created IrdaAddress.* OLD/TextStream has been updated
Diffstat (limited to 'comm/Multiplexer.cc')
-rw-r--r--comm/Multiplexer.cc722
1 files changed, 0 insertions, 722 deletions
diff --git a/comm/Multiplexer.cc b/comm/Multiplexer.cc
deleted file mode 100644
index b879ce6..0000000
--- a/comm/Multiplexer.cc
+++ /dev/null
@@ -1,722 +0,0 @@
-/*
- * The Unix Channel
- *
- * by Michel Beaudouin-Lafon
- *
- * Copyright 1990-1997
- * Laboratoire de Recherche en Informatique (LRI)
- *
- * Channel sets, or multiplexers
- *
- * $Id$
- * $CurLog$
- */
-
-#include "Multiplexer.h"
-#include "TimeOut.h"
-#include "SignalHandler.h"
-
-#include <signal.h> // for NSIG
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <memory.h>
-#include <setjmp.h>
-
-#if defined(__hpux) && !defined(__GNUG__)
-#define FD_SET_TYPE(x) ((int*) x)
-#else
-#define FD_SET_TYPE(x) (x)
-#endif
-
-#ifdef __osf__
-extern "C" int select (int, fd_set*, fd_set*, fd_set*, struct timeval*);
-#endif
-
-extern int errno;
-
-UchBaseMultiplexer* UchMpx = 0;
-
-#ifndef FD_SET
-#ifndef NFDBITS
-#define FD_SET(n, p) ((p)->fds_bits[0] |= (1 << (n)))
-#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1 << (n)))
-#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1 << (n)))
-#define FD_ZERO(p) ((p)->fds_bits[0] = 0)
-#else
-#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
-#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
-#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
-#define FD_ZERO(p) memset((char *)(p), 0, sizeof(*(p)))
-#endif
-#endif
-
-
-/*?class UchBaseMultiplexer
-Multiplexers make it possible to handle several communication channels at the
-same time; their implementation is based on the Unix \com{select} system call
-or similar mechanisms. Multiplexers are also able to implement safe (ie. not
-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.
-
-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
-called before actually scanning. For example that's the case for a connection
-with the X server, when some pending events have been buffered into the
-client by the previous \fun{HandleRead} call and need to be processed.
-
-Multiplexers may have different implementations, depending on the
-environment. When no other library is involved, they are simply
-implemented on top of Unix. But if \uch\ channels have to be mixed
-with the X Toolkit for instance, the implementation uses the
-mechanisms provided by the X Toolkit to add new channels. The same
-holds for Tcl/Tk or other environments. Every such implentation
-corresponds to a derived class of \typ{UchBaseMultiplexer}, which
-offers a uniform interface that hides the implementation
-differences. See the class \typ{UchMultiplexer} for a ``pure \uch''
-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 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.
-
-?*/
-
-/*?
-Create an empty channel set.
-?*/
-UchBaseMultiplexer :: UchBaseMultiplexer ()
-: DnnBaseMultiplexer (),
- Channels (new (UchChannel*) [NFILE]),
- Timers (),
- ReadCount (0),
- WriteCount (0),
- SelectCount (0),
- SigFired (false),
- Handlers (new UchBaseSignalHandler* [NSIG]),
- NbSignals (new int [NSIG])
-{
- memset (Handlers, 0, NSIG * sizeof (UchBaseSignalHandler*));
- memset (NbSignals, 0, NSIG * sizeof (int));
- memset (Channels, 0, NFILE * sizeof (UchChannel*));
-}
-
-/*?nodoc?*/
-UchBaseMultiplexer :: ~UchBaseMultiplexer ()
-{
-#ifdef CPLUS_BUG4
- delete [NFILE] Channels;
- delete [NSIG] NbSignals;
- delete [NSIG] Handlers;
-#else
- delete [] Channels;
- delete [] NbSignals;
- delete [] Handlers;
-#endif
- 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.
-?*/
-UchChannel*
-UchBaseMultiplexer :: operator [] (int fd)
-{
- return (fd < 0 || fd >= NFILE) ? 0 : Channels [fd];
-}
-
-/*?
-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 || fd >= NFILE)
- return false;
- UchChannel* ochan = Channels [fd];
- if (ochan)
- ochan->Remove ();
- Channels [fd] = chan;
- SetMasks (fd, chan->IOMode ());
- return true;
-}
-
-
-/*?
-Remove a channel from the set. This function can be passed a \var{UchChannel}.
-?*/
-bool
-UchBaseMultiplexer :: Remove (int fd)
-{
- if (fd < 0 || fd >= NFILE)
- return false;
- UchChannel* ch = Channels [fd];
- if (ch) {
- SetMasks (fd, IONone);
- Channels [fd] = 0;
- }
- return true;
-}
-
-/*?
-Remove all channels from this channel set.
-This function calls \fun{Remove} for all channels of the set.
-This is a way of exiting from \fun{LoopScan}.
-?*/
-void
-UchBaseMultiplexer :: RemoveAll ()
-{
- for (int fd = 0; fd < NFILE; fd++) {
- UchChannel* ch = Channels [fd];
- if (ch)
- ch->Remove (); // Calls UchBaseMultiplexer::Remove
- }
-}
-
-/*?
-Change the mode of a channel in the set.
-Mode \var{IONone} makes the channel inactive (without removing it).
-This function can be passed a \var{UchChannel}.
-?*/
-void
-UchBaseMultiplexer :: SetMode (int fd, IOMODE mode)
-{
- if (fd < 0)
- return;
-
- SetMasks (fd, mode);
- Channels [fd] -> SetMode (mode);
-}
-
-
-/*!
-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]++;
-
-}
-
-/*!
-This virtual function is called the first time when a signal is received by a
-signal handler associated to the multiplexer. It makes it possible
-to call implementation-dependant functions that defer the handling to
-safer times.
-!*/
-/*
-Does not need to be defined in UchMultiplexer, because
-they use the flag SigFired.
-*/
-/*?hidden?*/
-void
-UchBaseMultiplexer :: AddSignalHook ()
-{
-}
-
-/*!
-This function triggers the handling of all deferred signals. It should be
-called when \fun{AddSignalHook} has been called and the times are safe.
-!*/
-/*?hidden?*/
-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;
- }
-}
-
-/*?hidden?*/
-void
-UchBaseMultiplexer :: SetMasks (int, IOMODE)
-{
-}
-
-static jmp_buf reset_run;
-
-class UchMpxAborter : public UchBaseSignalHandler {
-public:
- UchMpxAborter (UchBaseMultiplexer& m, int s) : UchBaseSignalHandler (m, s) {}
- void DeferredHandle (int) { MyMpx.Abort (); }
-};
-
-/*?
-Run a multiplexer: make it repeatedly scan its channels, and take the
-appropriate actions. This function will exit under a number of
-circumstances, reflected by its return value.
-\small
-\begin{tabular}{ll}
-\var{isMpxTerminated}&the method \fun{Close} has been called.\\
-\var{isMpxEmpty}&there are no more channels in the set.\\
-\var{isMpxAborted}&the method \fun{Abort} has been called,
-or signals SIGINT or SIGTERM were received.\\
-\var{isMpxError}&an error has occured.
-\end{tabular}
-?*/
-MPX_RES
-UchBaseMultiplexer :: Run ()
-{
- if (setjmp (reset_run))
- return isMpxAborted;
-
- UchMpxAborter h1 (*this, SigTerm);
- UchMpxAborter h2 (*this, SigInt);
-
- return Loop ();
-}
-
-/*?
-Remove all channels from the multiplexer, thus stopping it if running.
-?*/
-void
-UchBaseMultiplexer :: Close ()
-{
- RemoveAll ();
- Looping = false;
-}
-
-/*?
-Stop the multiplexer, without cleaning it.
-?*/
-void
-UchBaseMultiplexer :: Abort ()
-{
- if (Looping)
- longjmp (reset_run, 1);
-}
-
-/*?class UchMultiplexer
-The class \typ{UchMultiplexer} is the default implementation of multiplexers,
-used when there are no compatibility needs. For historical reasons, it offers
-a number of additional methods.
-?*/
-
-/*?
-Build an empty multiplexer.
-?*/
-UchMultiplexer :: UchMultiplexer ()
-: UchBaseMultiplexer (),
- TimeOut (-1),
- Looping (false),
- Hooks ()
-
-{
- FD_ZERO (&ReadMask);
- FD_ZERO (&WriteMask);
- FD_ZERO (&SelectMask);
-}
-
-/*?nodoc?*/
-UchMultiplexer :: ~UchMultiplexer ()
-{
-}
-
-
-
-// update the masks when channel fd changes its mode
-//
-/*?hidden?*/
-void
-UchMultiplexer :: SetMasks (int fd, IOMODE mode)
-{
- if (mode & IORead) {
- if (! FD_ISSET (fd, &ReadMask)) {
- ReadCount++;
- FD_SET (fd, &ReadMask);
- }
- } else {
- if (FD_ISSET (fd, &ReadMask)) {
- FD_CLR (fd, &ReadMask);
- ReadCount--;
- }
- }
-
- if (mode & IOWrite) {
- if (! FD_ISSET (fd, &WriteMask)) {
- WriteCount++;
- FD_SET (fd, &WriteMask);
- }
- } else {
- if (FD_ISSET (fd, &WriteMask)) {
- FD_CLR (fd, &WriteMask);
- WriteCount--;
- }
- }
-
- if (mode & IOSelect) {
- if (! FD_ISSET (fd, &SelectMask)) {
- SelectCount++;
- FD_SET (fd, &SelectMask);
- }
- } else {
- if (FD_ISSET (fd, &SelectMask)) {
- FD_CLR (fd, &SelectMask);
- SelectCount--;
- }
- }
-
-}
-
-#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)
-{
- fd_set rmsk, wmsk;
- int nfd, ret = -1;
- register int fd;
- struct timeval tv;
- struct timeval* timeout = 0;
-
- if (poll) {
- timeout = &tv;
- tv.tv_sec = tv.tv_usec = 0;
- }
-
- while (ret <= 0) {
- if (ReadCount == 0 && WriteCount == 0 && SelectCount == 0) {
- ExecHooks (true);
- return 0;
- }
- ExecHooks (false);
-
- rmsk = ReadMask;
- wmsk = WriteMask;
-
- /* let's fiddle with ret to skip select if we are late with timers */
- ret = -1;
- if (!poll && TimeOut != -1) {
- CcuTimeStamp now;
- Millisecond delay = TimeOut - now;
- /* if delay < 0, select is unhappy */
- if (delay < 0)
- ret = 0;
- tv.tv_sec = delay / 1000;
- tv.tv_usec = 1000 * (delay % 1000);
- timeout = &tv;
- }
-
- /* skipping select is a trick to avoid problems with timers. However,
- something more general should be done to:
- - 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... */
- CcuCoreTimer::Fire (&Timers);
- else if (!poll)
- fprintf (stderr, "select returned 0 without reason!\n");
- return 0;
-
- /* Handle errors */
- } else if (ret < 0) {
- if (nointr && ret == -1 && errno == EINTR)
- continue;
- else {
- ExecHooks (true);
- return ret;
- }
- }
- }
-
-
- /* Finally, handle pending input and output */
- for (fd = 0, nfd = ret; nfd; fd++) {
- if (FD_ISSET (fd, &wmsk)) {
- nfd--;
- UchChannel* ch = Channels [fd];
- if (ch)
- ch->HandleWrite ();
- }
- if (FD_ISSET (fd, &rmsk)) {
- nfd--;
- UchChannel* ch = Channels [fd];
- if (ch)
- ch->HandleRead ();
- }
- }
-
- return ret;
-}
-
-
-/*?
-Scan the channels in the set and call the channel's handlers.
-First the select handler (\fun{UchChannel::HandleSelect}) of each channel with mode
-\var{IOSelect} is called.
-If it returns true, \fun{Scan} exits immediately, while \fun{LoopScan} loops immediately.
-If no select handler returns true, the system call \fun{select} is used to poll or
-wait for the channels that are ready.
-When the select returns normally, the write handlers \fun{HandleWrite} of the
-channels in mode \var{IOWrite} that are ready to write are called, and
-the read handlers (\fun{HandleRead}) of the channels in mode \fun{IORead}
-that are ready to read are called.
-If \var{nointr} is true, ignore the interrupted system calls, else return an error
-whenever the \fun{select} system call is interrupted.
-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{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{Stop} or \fun{Close} was called.
-?*/
-MPX_RES
-UchMultiplexer :: LoopScan (bool nointr)
-{
- fd_set rmsk, wmsk;
- register int nb_pending_fd, fd, fd0;
- Looping = true;
-
- for (fd0 = 0; Looping; fd0 < NFILE ? fd0++ : (fd0 = 0)) {
-
- /* First, handle signals */
- if (SigFired)
- HandleDeferredSignals ();
-
-#if 0
- /* Then, timers */
- CcuCoreTimer::Fire (&Timers);
-#endif
- /* Then, check I/Os */
- if (ReadCount == 0 && WriteCount == 0 && SelectCount == 0) {
- ExecHooks (true);
- return isMpxEmpty;
- }
-
- /* Then other hooks */
- ExecHooks (false);
-
- /* Lets get ready for calling select: set masks and compute next time out.
- We fiddle with nb_pending_fd to skip select if we are late with timers */
- nb_pending_fd = -1;
- rmsk = ReadMask;
- wmsk = WriteMask;
- struct timeval tv;
- struct timeval* timeout = 0;
- if (TimeOut != -1) {
- CcuTimeStamp now;
- Millisecond delay = TimeOut - now;
- if (delay < 0)
- nb_pending_fd = 0;
- tv.tv_sec = delay / 1000;
- tv.tv_usec = 1000 * (delay % 1000);
- timeout = &tv;
- }
-
- /* Call select, except if late with timers */
- if (nb_pending_fd != 0)
- nb_pending_fd = select (NFILE, FD_SET_TYPE(&rmsk), FD_SET_TYPE(&wmsk), 0, timeout);
- /* Handle time out */
- if (nb_pending_fd == 0) {
- if (TimeOut != -1)
- CcuCoreTimer::Fire (&Timers);
- else
- fprintf (stderr, "select returned 0 without reason!\n");
- continue;
-
- /* Handle errors */
- } else if (nb_pending_fd < 0) {
- if (nointr && nb_pending_fd == -1 && errno == EINTR)
- continue;
- else {
- ExecHooks (true);
- return isMpxError;
- }
- }
-
- /* Finally, handle pending input and output */
- for (fd = fd0; nb_pending_fd; (fd < NFILE) ? fd++ : (fd = 0)) {
- if (FD_ISSET (fd, &wmsk)) {
- nb_pending_fd--;
- Channels[fd]->HandleWrite ();
- if (! Looping) {
- ExecHooks (true);
- return isMpxTerminated;
- }
- }
- if (FD_ISSET (fd, &rmsk)) {
- nb_pending_fd--;
- Channels[fd]->HandleRead ();
- if (! Looping) {
- ExecHooks (true);
- return isMpxTerminated;
- }
- }
- }
- }
-
- ExecHooks (true);
- return isMpxTerminated;
-}
-
-/*?nodoc?*/
-char*
-UchMultiplexer :: StrRepr (char* buf)
-{
- sprintf (buf, "R:%ux W:%ux", ReadMask, WriteMask);
- return buf;
-}
-
-/*?hidden?*/
-void
-UchMultiplexer :: SetTimeOut (Millisecond delay)
-{
- CcuTimeStamp now;
- TimeOut = now + delay;
-}
-
-/*?hidden?*/
-void
-UchMultiplexer :: SuppressTimeOut ()
-{
- TimeOut = -1;
-}
-
-/*?hidden?*/
-MPX_RES
-UchMultiplexer :: Loop ()
-{
- return LoopScan ();
-}
-
-
-void
-UchMultiplexer :: Stop ()
-{
- Looping = false;
-}
-
-
-void
-UchMultiplexer :: AddHook (UchMpxHook* h, bool final)
-{
- Hooks.Append ((void*) h);
- if (final)
- FinalHooks.Append ((void*) h);
-}
-
-void
-UchMultiplexer :: RemoveHook (UchMpxHook* h, bool final)
-{
- Hooks.Remove ((void*) h);
- if (final)
- FinalHooks.Remove ((void*) h);
-}
-
-void
-UchMultiplexer :: AddFinalHook (UchMpxHook* h)
-{
- FinalHooks.Append ((void*) h);
-}
-
-void
-UchMultiplexer :: RemoveFinalHook (UchMpxHook* h)
-{
- FinalHooks.Remove ((void*) h);
-}
-
-
-void
-UchMultiplexer :: ExecHooks (bool final)
-{
- CcuList* hooks = final ? &FinalHooks : &Hooks;
- CcuListIter li = *hooks;
- while (++li) {
- UchMpxHook* h = (UchMpxHook*) *li;
- (*h)();
- }
-}
-
-void
-UchOpen (UchBaseMultiplexer* m)
-{
- UchMpx = m ? m : new UchMultiplexer;
- DnnMpx = UchMpx;
-}
-
-MPX_RES
-UchLoop ()
-{
- return UchMpx->Loop ();
-}
-
-void
-UchStop ()
-{
- UchMpx->Stop ();
-}