guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 01/23: add (ice-9 nio)


From: Andy Wingo
Subject: [Guile-commits] 01/23: add (ice-9 nio)
Date: Thu, 24 Mar 2016 14:26:02 +0000

wingo pushed a commit to branch wip-ethreads
in repository guile.

commit c1f69f19ac3584ee24a772f59d9078e5f5259a74
Author: Andy Wingo <address@hidden>
Date:   Fri Mar 16 18:13:06 2012 +0100

    add (ice-9 nio)
    
    * module/ice-9/nio.scm: New module, providing nonblocking I/O
      primitives.
    
    * libguile/nio.c:
    * libguile/nio.h: New files, providing non-blocking read(2), write(2),
      and accept(2) primitives.
    
    * libguile/init.c:
    * libguile/Makefile.am:
    * module/Makefile.am: Add to build.
---
 libguile/Makefile.am |    2 +
 libguile/init.c      |    2 +
 libguile/nio.c       |  197 ++++++++++++++++++++++++++++++++++++++++++++++++++
 libguile/nio.h       |   30 ++++++++
 module/Makefile.am   |    1 +
 module/ice-9/nio.scm |   46 ++++++++++++
 6 files changed, 278 insertions(+), 0 deletions(-)

diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index 3bc9952..ac7aad3 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -175,6 +175,7 @@ address@hidden@_la_SOURCES =                                
\
        mallocs.c                               \
        memoize.c                               \
        modules.c                               \
+       nio.c                                   \
        null-threads.c                          \
        numbers.c                               \
        objprop.c                               \
@@ -620,6 +621,7 @@ modinclude_HEADERS =                                \
        memoize.h                               \
        modules.h                               \
        net_db.h                                \
+       nio.h                                   \
        null-threads.h                          \
        numbers.h                               \
        objprop.h                               \
diff --git a/libguile/init.c b/libguile/init.c
index dd63574..da6e145 100644
--- a/libguile/init.c
+++ b/libguile/init.c
@@ -82,6 +82,7 @@
 #include "libguile/memoize.h"
 #include "libguile/modules.h"
 #include "libguile/net_db.h"
+#include "libguile/nio.h"
 #include "libguile/numbers.h"
 #include "libguile/loader.h"
 #include "libguile/objprop.h"
@@ -402,6 +403,7 @@ scm_i_init_guile (void *base)
   scm_register_foreign_object ();
   scm_register_srfi_1 ();
   scm_register_srfi_60 ();
+  scm_register_nio ();
   scm_register_poll ();
 
   scm_init_strings ();            /* Requires array-handle */
diff --git a/libguile/nio.c b/libguile/nio.c
new file mode 100644
index 0000000..bebb059
--- /dev/null
+++ b/libguile/nio.c
@@ -0,0 +1,197 @@
+/* Copyright (C) 2016 Free Software Foundation, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+
+
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "libguile/_scm.h"
+#include "libguile/bytevectors.h"
+#include "libguile/error.h"
+#include "libguile/numbers.h"
+#include "libguile/socket.h"
+#include "libguile/validate.h"
+
+#include "libguile/nio.h"
+
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#else
+#include <sys/socket.h>
+#ifdef HAVE_UNIX_DOMAIN_SOCKETS
+#include <sys/un.h>
+#endif
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#endif
+
+
+
+/* {Non-blocking I/O}
+ */
+
+/* Read COUNT bytes from FD into BV, and write them at POS.  Return the
+   number of bytes read, or -1 if no bytes could be read without
+   blocking.  A return value of 0 indicates EOF.
+ */
+static SCM
+scm_nio_read (SCM fd, SCM bv, SCM pos, SCM count)
+#define FUNC_NAME "nio-read"
+{
+  int c_fd;
+  ssize_t rv;
+  signed char *data;
+  size_t c_pos, c_count;
+  int try_again;
+
+  c_fd = scm_to_int (fd);
+  SCM_VALIDATE_BYTEVECTOR (SCM_ARG2, bv);
+  data = SCM_BYTEVECTOR_CONTENTS (bv);
+  c_pos = scm_to_size_t (pos);
+  c_count = scm_to_size_t (count);
+  
+  if (SCM_UNLIKELY (SCM_BYTEVECTOR_LENGTH (bv) < c_pos))
+    SCM_OUT_OF_RANGE (SCM_ARG3, pos);
+  if (SCM_UNLIKELY (c_count > SCM_BYTEVECTOR_LENGTH (bv) - c_pos))
+    SCM_OUT_OF_RANGE (SCM_ARG4, count);
+
+  data += c_pos;
+
+  rv = read (c_fd, data, c_count);
+  try_again = (errno == EWOULDBLOCK || errno == EAGAIN);
+
+  if (rv < 0 && !try_again)
+    SCM_SYSERROR;
+  if (rv <= 0 && try_again)
+    return scm_from_ssize_t (-1);
+  else
+    return scm_from_ssize_t (rv);
+}
+#undef FUNC_NAME
+
+/* Write to FD the COUNT bytes from BV starting at POS.  Return the
+   number of bytes written, which may be less than COUNT if a write would
+   block.
+ */
+static SCM
+scm_nio_write (SCM fd, SCM bv, SCM pos, SCM count)
+#define FUNC_NAME "nio-write"
+{
+  int c_fd;
+  ssize_t rv;
+  signed char *data;
+  size_t c_pos, c_count;
+  int try_again;
+
+  c_fd = scm_to_int (fd);
+  SCM_VALIDATE_BYTEVECTOR (SCM_ARG2, bv);
+  data = SCM_BYTEVECTOR_CONTENTS (bv);
+  c_pos = scm_to_size_t (pos);
+  c_count = scm_to_size_t (count);
+  
+  if (SCM_UNLIKELY (SCM_BYTEVECTOR_LENGTH (bv) < c_pos))
+    SCM_OUT_OF_RANGE (SCM_ARG3, pos);
+  if (SCM_UNLIKELY (c_count > SCM_BYTEVECTOR_LENGTH (bv) - c_pos))
+    SCM_OUT_OF_RANGE (SCM_ARG4, count);
+
+  data += c_pos;
+
+  rv = write (c_fd, data, c_count);
+  try_again = (errno == EWOULDBLOCK || errno == EAGAIN);
+
+  if (rv < 0 && !try_again)
+    SCM_SYSERROR;
+
+  return scm_from_ssize_t ((rv < 0) ? 0 : rv);
+}
+#undef FUNC_NAME
+
+/* The largest possible socket address.  Wrapping it in a union guarantees
+   that the compiler will make it suitably aligned.  */
+typedef union
+{
+  struct sockaddr     sockaddr;
+  struct sockaddr_in  sockaddr_in;
+
+#ifdef HAVE_UNIX_DOMAIN_SOCKETS
+  struct sockaddr_un  sockaddr_un;
+#endif
+#ifdef HAVE_IPV6
+  struct sockaddr_in6 sockaddr_in6;
+#endif
+} scm_t_max_sockaddr;
+
+/* Like @code{accept}, but instead of returning a pair whose
+   @emph{car} is a port, returns a pair whose @emph{car} is a
+   file descriptor.  Also, if the @code{accept} call failed with
+   @code{EAGAIN} or @code{EWOULDBLOCK}, returns @code{#f} instead
+   of throwing an exception. */
+static SCM
+scm_nio_accept (SCM fd)
+#define FUNC_NAME "nio-accept"
+{
+  int c_fd;
+  int newfd;
+  socklen_t addr_size = sizeof (scm_t_max_sockaddr);
+  scm_t_max_sockaddr addr;
+
+  c_fd = scm_to_int (fd);
+  newfd = accept (c_fd, (struct sockaddr *) &addr, &addr_size);
+
+  if (newfd >= 0)
+    return scm_cons (scm_from_int (newfd),
+                     scm_from_sockaddr ((struct sockaddr *) &addr, addr_size));
+  else if (errno == EAGAIN || errno == EWOULDBLOCK)
+    return SCM_BOOL_F;
+  else
+    SCM_SYSERROR;
+}
+#undef FUNC_NAME
+
+
+
+
+/* Low-level helpers for (ice-9 nio).  */
+static void
+scm_init_nio (void)
+{
+  scm_c_define_gsubr ("%nio-read", 4, 0, 0, scm_nio_read);
+  scm_c_define_gsubr ("%nio-write", 4, 0, 0, scm_nio_write);
+  scm_c_define_gsubr ("%nio-accept", 1, 0, 0, scm_nio_accept);
+}
+
+void
+scm_register_nio (void)
+{
+  scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
+                            "scm_init_nio",
+                           (scm_t_extension_init_func) scm_init_nio,
+                           NULL);
+}
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
diff --git a/libguile/nio.h b/libguile/nio.h
new file mode 100644
index 0000000..152bebb
--- /dev/null
+++ b/libguile/nio.h
@@ -0,0 +1,30 @@
+#ifndef SCM_NIO_H
+#define SCM_NIO_H
+
+/* Copyright (C) 2016 Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+
+
+#include "libguile/__scm.h"
+
+
+
+SCM_INTERNAL void scm_register_nio (void);
+
+#endif  /* SCM_NIO_H */
diff --git a/module/Makefile.am b/module/Makefile.am
index 6cb1603..6120760 100644
--- a/module/Makefile.am
+++ b/module/Makefile.am
@@ -76,6 +76,7 @@ SOURCES =                                     \
   ice-9/mapping.scm                            \
   ice-9/match.scm                              \
   ice-9/networking.scm                         \
+  ice-9/nio.scm                                        \
   ice-9/null.scm                               \
   ice-9/occam-channel.scm                      \
   ice-9/optargs.scm                            \
diff --git a/module/ice-9/nio.scm b/module/ice-9/nio.scm
new file mode 100644
index 0000000..b2f0e71
--- /dev/null
+++ b/module/ice-9/nio.scm
@@ -0,0 +1,46 @@
+;; Non-Blocking I/O
+
+;;;; Copyright (C) 2016 Free Software Foundation, Inc.
+;;;; 
+;;;; This library is free software; you can redistribute it and/or
+;;;; modify it under the terms of the GNU Lesser General Public
+;;;; License as published by the Free Software Foundation; either
+;;;; version 3 of the License, or (at your option) any later version.
+;;;; 
+;;;; This library is distributed in the hope that it will be useful,
+;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;;; Lesser General Public License for more details.
+;;;; 
+;;;; You should have received a copy of the GNU Lesser General Public
+;;;; License along with this library; if not, write to the Free Software
+;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
USA
+;;;; 
+
+(define-module (ice-9 nio)
+  #:export (nio-read
+            nio-write
+            nio-accept))
+
+(eval-when (eval load compile)
+  (load-extension (string-append "libguile-" (effective-version))
+                  "scm_init_nio"))
+
+(define (nio-read fd bv pos count)
+  "Read @var{count} bytes from @var{fd} into @var{bv}, and write them at
address@hidden  Return the number of bytes read, or -1 if no bytes could be
+read without blocking.  A return value of 0 indicates EOF."
+  (%nio-read fd bv pos count))
+
+(define (nio-write fd bv pos count)
+  "Write to @var{fd} the @var{count} bytes from @var{bv} starting at
address@hidden  Return the number of bytes written, which may be less than
address@hidden if a write would block."
+  (%nio-write fd bv pos count))
+
+(define (nio-accept fd)
+  "Accept a new connection on the socket whose file descriptor is
address@hidden  Return a pair whose @emph{car} is a file descriptor of the
+new client socket, unless the @code{accept} call would have blocked, in
+which case return @code{#f}."
+  (%nio-accept fd))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]