From 064567b95b91462ca310d1f94ef7df8646632e48 Mon Sep 17 00:00:00 2001
From: sof <unknown>
Date: Sat, 11 Sep 1999 16:49:03 +0000
Subject: [PATCH] [project @ 1999-09-11 16:49:02 by sof] Added hSelect

---
 ghc/lib/misc/Select.lhs         | 128 ++++++++++++++++++++++++++++++++
 ghc/lib/misc/cbits/selectFrom.c |  72 ++++++++++++++++++
 ghc/lib/misc/cbits/selectFrom.h |  21 ++++++
 3 files changed, 221 insertions(+)
 create mode 100644 ghc/lib/misc/Select.lhs
 create mode 100644 ghc/lib/misc/cbits/selectFrom.c
 create mode 100644 ghc/lib/misc/cbits/selectFrom.h

diff --git a/ghc/lib/misc/Select.lhs b/ghc/lib/misc/Select.lhs
new file mode 100644
index 000000000000..4fdf3ac7aaf0
--- /dev/null
+++ b/ghc/lib/misc/Select.lhs
@@ -0,0 +1,128 @@
+%
+% (c) sof, 1999
+%
+
+Haskell wrapper for select() OS functionality. It's use
+shouldn't be all that common in a Haskell system that implements
+IO in such a way that's thread friendly, but still.
+
+\begin{code}
+{-# OPTIONS -#include "cbits/selectFrom.h" #-}
+module Select
+    (
+      hSelect     -- :: [Handle]
+                  -- -> [Handle]
+		  -- -> [Handle]
+		  -- -> TimeOut
+		  -- -> IO SelectResult
+    , TimeOut(..) -- type _ = Maybe Int
+    , SelectResult(..) 
+    ) where
+
+import Posix
+import GlaExts
+import IO
+import Monad
+import Maybe
+import PrelIOBase
+import PosixUtil (fdToInt)
+
+\end{code}
+
+This stuff should really be done using HDirect.
+
+\begin{code}
+type TimeOut
+ = Maybe Int
+    -- Nothing => wait indefinitely.
+    -- Just x | x >= 0    => block waiting for 'x' micro seconds.
+    --        | otherwise => block waiting for '-x' micro seconds.
+
+type SelectResult
+ = ([Handle], [Handle], [Handle])
+
+hSelect :: [Handle]  -- input/read handles
+        -> [Handle]  -- output/write handles
+	-> [Handle]  -- exceptional handles
+	-> TimeOut
+	-> IO SelectResult
+hSelect ins outs excps timeout = do
+     ins_         <- mapM getFd ins
+     outs_        <- mapM getFd outs
+     excps_       <- mapM getFd excps
+     (max_in,  fds_ins)   <- marshallFDs ins_
+     (max_out, fds_outs)  <- marshallFDs outs_
+     (max_excp,fds_excps) <- marshallFDs excps_
+     tout                 <- marshallTimeout timeout
+     let max_fd = max_in `max` max_out `max` max_excp
+     rc                <- selectFrom__ fds_ins
+     				       fds_outs
+				       fds_excps
+				       (max_fd+1) tout
+     if (rc /= 0)
+      then constructErrorAndFail "hSelect"
+      else
+         let 
+	   -- thunk these so that we only pay unmarshalling costs if demanded.
+	  ins_ready   = unsafePerformIO (getReadyOnes fds_ins ins_)
+          outs_ready  = unsafePerformIO (getReadyOnes fds_outs outs_)
+          excps_ready = unsafePerformIO (getReadyOnes fds_outs outs_)
+	 in
+	 return (ins_ready, outs_ready, excps_ready)
+
+getFd :: Handle -> IO (Fd,Handle)
+getFd h = do
+  f <- handleToFd h
+  return (f,h)
+
+foreign import "selectFrom__" 
+		selectFrom__ :: ByteArray Int
+			     -> ByteArray Int
+			     -> ByteArray Int
+			     -> Int
+			     -> Int
+			     -> IO Int
+
+marshallTimeout :: Maybe Int -> IO Int
+marshallTimeout Nothing  = return (-1)
+marshallTimeout (Just x) = return (abs x)
+
+getReadyOnes :: ByteArray Int -> [(Fd,Handle)] -> IO [Handle]
+getReadyOnes ba ls = do
+  xs <- mapM isReady ls
+  return (catMaybes xs)
+ where
+  isReady (f,h) = do
+     let fi = fdToInt f
+     flg <- is_fd_set ba fi
+     if (flg /= 0) then
+        return (Just h)
+      else 
+        return Nothing
+
+marshallFDs :: [(Fd,Handle)] -> IO (Int, ByteArray Int)
+marshallFDs ls = do
+  ba <- stToIO (newCharArray (0, sizeof_fd_set))
+  fd_zero ba
+  let
+   fillIn acc (f,_) = do
+     let fi = fdToInt f
+     fd_set ba fi
+     return (max acc fi)
+  x  <- foldM fillIn 0 ls
+  ba <- stToIO (unsafeFreezeByteArray ba)
+  return (x, ba)
+
+foreign import "is_fd_set__"
+	       is_fd_set :: ByteArray Int -> Int -> IO Int
+
+foreign import "fd_zero__"
+	       fd_zero :: MutableByteArray RealWorld Int -> IO ()
+
+foreign import "fd_set__"
+	       fd_set :: MutableByteArray RealWorld Int -> Int -> IO ()
+
+foreign import "sizeof_fd_set__"
+	       sizeof_fd_set :: Int
+
+\end{code}
diff --git a/ghc/lib/misc/cbits/selectFrom.c b/ghc/lib/misc/cbits/selectFrom.c
new file mode 100644
index 000000000000..55e6516ef34f
--- /dev/null
+++ b/ghc/lib/misc/cbits/selectFrom.c
@@ -0,0 +1,72 @@
+/*
+ * (c) sof, 1999
+ *
+ * Stubs to help implement Select module.
+ */
+
+/* we're outside the realms of POSIX here... */
+#define NON_POSIX_SOURCE
+
+#include "Rts.h"
+#include "selectFrom.h"
+#include "stgio.h"
+
+# if defined(HAVE_SYS_TYPES_H)
+#  include <sys/types.h>
+# endif
+
+# ifdef HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# endif
+
+
+/* Helpers for the Haskell-side unmarshalling */
+
+int
+sizeof_fd_set__()
+{
+ return (sizeof(fd_set));
+}
+
+void
+fd_zero__(StgByteArray a)
+{
+  FD_ZERO((fd_set*)a);
+}
+
+void
+fd_set__(StgByteArray a, StgInt fd)
+{
+  FD_SET(fd,(fd_set*)a);
+}
+
+int
+is_fd_set__(StgByteArray a, StgInt fd)
+{
+  return FD_ISSET(fd,(fd_set*)a);
+}
+
+StgInt
+selectFrom__( StgByteArray rfd
+            , StgByteArray wfd
+	    , StgByteArray efd
+	    , StgInt mFd
+	    , StgInt tout
+	    )
+{
+ int rc, i;
+ struct timeval tv;
+
+ if (tout != (-1)) {
+   tv.tv_sec = tout / 1000000;
+   tv.tv_usec = tout % 1000000;
+ }
+
+ while ((rc = select(mFd, (fd_set*)rfd, (fd_set*)wfd, (fd_set*)efd, (tout == -1 ? NULL : &tv))) < 0) {
+      if (errno != EINTR) {
+	break;
+      }
+ }
+ return 0;
+}
+
diff --git a/ghc/lib/misc/cbits/selectFrom.h b/ghc/lib/misc/cbits/selectFrom.h
new file mode 100644
index 000000000000..7504df051468
--- /dev/null
+++ b/ghc/lib/misc/cbits/selectFrom.h
@@ -0,0 +1,21 @@
+/*
+ * (c) sof, 1999
+ *
+ * Stubs to help implement Select module
+ */
+#ifndef __SELECTFROM_H__
+#define __SELECTFROM_H__
+
+extern StgInt sizeof_fd_set__();
+extern void fd_zero__(StgByteArray fds);
+extern void fd_set__(StgByteArray a, StgInt fd);
+extern StgInt is_fd_set__(StgByteArray a, StgInt fd);
+extern StgInt selectFrom__
+            ( StgByteArray rfd
+            , StgByteArray wfd
+	    , StgByteArray efd
+	    , StgInt mFd
+	    , StgInt tout
+	    );
+
+#endif /* __SELECTFROM_H__ */
-- 
GitLab