unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: ludovic.courtes@laas.fr (Ludovic Courtès)
To: Guile-Devel <guile-devel@gnu.org>
Subject: Re: Unbuffered socket I/O
Date: Wed, 28 Feb 2007 10:47:58 +0100	[thread overview]
Message-ID: <87fy8qlik1.fsf@laas.fr> (raw)
In-Reply-To: <87slcsfqk4.fsf@zip.com.au> (Kevin Ryde's message of "Tue, 27 Feb 2007 10:27:07 +1100")

[-- Attachment #1: Type: text/plain, Size: 1851 bytes --]

Hi,

Kevin Ryde <user42@zip.com.au> writes:

> ludovic.courtes@laas.fr (Ludovic Courtès) writes:
>>
>> Right.  That's an incompatible change if the _output_ is buffered.
>> Input can be buffered, though, without this being visible by users.
>
> Alas, that too is in an incompatible change, because recv! ignores
> buffering.

Hmm, right.

> Sounds good.  Perhaps `setvbuf-input' and `setvbuf-output' for the two
> directions.  They could go in 1.8 too if you're careful with the
> implementation.

Below is a tentative patch (I chose more meaningful names since they
don't relate to `setvbuf(3)').  The issue is that it duplicates fport
buffering logic, but I couldn't think of a nice way to factorize this
with, e.g., `scm_fport_buffer_add ()'.  What do you think?

Besides, how about applying the change I originally proposed to HEAD?
That would require changing `recv!', `send', etc. so that they are
somehow "buffering-aware".  Ideally, it would be nice if they didn't
break through the port abstraction as they currently do, but I don't
know how that could be implemented (what should be the meaning of
`MSG_DONTROUTE' on an input string buffer?  ;-)).

>> It
>> does nothing for O_NONBLOCK streams and waits for events otherwise.
>> Since, for blocking streams, `read ()' does not return until either EOF
>> is reached or at least one octet was read, `fport_wait_for_input ()'
>> seems redundant.
>
> Ahh, hang on, I wonder if it's a hack to do an "exit guile" while
> blocked within a read(), thus allowing gc to run in other threads.

Indeed, `scm_std_select ()' does a "leave guile".

> If that's true then presumably the write side is afflicted too, as
> well as various other potentially blocking operations like
> read-string!/partial and gethost.

Afflicted by what?

Thanks,
Ludovic.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Asymmetrical fport buffering. --]
[-- Type: text/x-patch, Size: 4273 bytes --]

--- orig/libguile/fports.c
+++ mod/libguile/fports.c
@@ -90,10 +90,10 @@
 /* default buffer size, used if the O/S won't supply a value.  */
 static const size_t default_buffer_size = 1024;
 
-/* create FPORT buffer with specified sizes (or -1 to use default size or
-   0 for no buffer.  */
+/* Create FPORT buffer with specified sizes (or -1 to use default size or
+   0 for no buffer).  */
 static void
-scm_fport_buffer_add (SCM port, long read_size, int write_size)
+scm_fport_buffer_add (SCM port, long read_size, long write_size)
 #define FUNC_NAME "scm_fport_buffer_add"
 {
   scm_t_port *pt = SCM_PTAB_ENTRY (port);
@@ -217,6 +217,115 @@
 }
 #undef FUNC_NAME
 
+SCM_DEFINE (scm_set_port_input_buffer_size_x, "set-port-input-buffer-size!",
+	    2, 0, 0,
+	    (SCM port, SCM size),
+	    "Use a @var{size}-octet input buffer for @var{port}, which "
+	    "must be a file or socket port.  The current input buffer "
+	    "of @var{port} must contain less than @var{size} octets.")
+#define FUNC_NAME s_scm_set_port_input_buffer_size_x
+{
+  scm_t_port *pt;
+  size_t c_size;
+
+  SCM_VALIDATE_FPORT (1, port);
+  c_size = scm_to_uint (size);
+
+  pt = SCM_PTAB_ENTRY (port);
+
+  if (pt->read_buf_size != c_size)
+    {
+      size_t c_offset, c_end;
+      unsigned char *new_buf;
+
+      c_end = pt->read_end - pt->read_buf;
+      c_offset = pt->read_pos - pt->read_buf;
+
+      if (c_offset > c_size)
+	scm_wrong_type_arg_msg (FUNC_NAME, 1, port,
+				"Input buffer must be flushed before it "
+				"can be shrunk");
+
+      if (c_size == 0)
+	new_buf = &pt->shortbuf, c_size = 1;
+      else
+	{
+	  if (pt->read_buf != &pt->shortbuf)
+	    new_buf = scm_gc_realloc (pt->read_buf,
+				      pt->read_buf_size, c_size,
+				      "port buffer");
+	  else
+	    new_buf = scm_gc_malloc (c_size, "port buffer");
+	}
+
+      pt->read_buf = new_buf;
+      pt->read_end = new_buf + c_end;
+      pt->read_pos = new_buf + c_offset;
+      pt->read_buf_size = c_size;
+
+      if ((pt->read_buf_size == 0) && (pt->write_buf_size == 0))
+	SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) | SCM_BUF0);
+    }
+
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_set_port_output_buffer_size_x, "set-port-output-buffer-size!",
+	    2, 0, 0,
+	    (SCM port, SCM size),
+	    "Use a @var{size}-octet output buffer for @var{port}, which "
+	    "must be a file or socket port.  The current output buffer of "
+	    "@var{port} must contain less than @var{size} octets.")
+#define FUNC_NAME s_scm_set_port_output_buffer_size_x
+{
+  scm_t_port *pt;
+  size_t c_size;
+
+  SCM_VALIDATE_FPORT (1, port);
+  c_size = scm_to_uint (size);
+
+  pt = SCM_PTAB_ENTRY (port);
+
+  if (pt->write_buf_size != c_size)
+    {
+      size_t c_offset, c_end;
+      unsigned char *new_buf;
+
+      c_end = pt->write_end - pt->write_buf;
+      c_offset = pt->write_pos - pt->write_buf;
+
+      if (c_offset > c_size)
+	scm_wrong_type_arg_msg (FUNC_NAME, 1, port,
+				"Output buffer must be flushed before it "
+				"can be shrunk");
+
+      if (c_size == 0)
+	new_buf = &pt->shortbuf, c_size = 1;
+      else
+	{
+	  if (pt->write_buf != &pt->shortbuf)
+	    new_buf = scm_gc_realloc (pt->write_buf,
+				      pt->write_buf_size, c_size,
+				      "port buffer");
+	  else
+	    new_buf = scm_gc_malloc (c_size, "port buffer");
+	}
+
+      pt->write_buf = new_buf;
+      pt->write_end = new_buf + c_end;
+      pt->write_pos = new_buf + c_offset;
+      pt->write_buf_size = c_size;
+
+      if ((pt->read_buf_size == 0) && (pt->write_buf_size == 0))
+	SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) | SCM_BUF0);
+    }
+
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+
 /* Move ports with the specified file descriptor to new descriptors,
  * resetting the revealed count to 0.
  */


--- orig/libguile/fports.h
+++ mod/libguile/fports.h
@@ -49,6 +49,8 @@
 \f
 SCM_API SCM scm_setbuf0 (SCM port);
 SCM_API SCM scm_setvbuf (SCM port, SCM mode, SCM size);
+SCM_API SCM scm_set_port_input_buffer_size_x (SCM port, SCM size);
+SCM_API SCM scm_set_port_output_buffer_size_x (SCM port, SCM size);
 SCM_API void scm_evict_ports (int fd);
 SCM_API SCM scm_open_file (SCM filename, SCM modes);
 SCM_API SCM scm_fdes_to_port (int fdes, char *mode, SCM name);




[-- Attachment #3: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

  reply	other threads:[~2007-02-28  9:47 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-02-23 17:09 Unbuffered socket I/O Ludovic Courtès
2007-02-23 22:36 ` Neil Jerram
2007-02-25 22:57 ` Kevin Ryde
2007-02-26 14:07   ` Ludovic Courtès
2007-02-26 20:32     ` Neil Jerram
2007-02-26 23:35       ` Kevin Ryde
2007-02-27  9:11       ` Ludovic Courtès
2007-02-28 21:24         ` Kevin Ryde
2007-03-01  9:10           ` Ludovic Courtès
2007-03-04 23:48             ` Kevin Ryde
2007-03-07  0:20             ` Kevin Ryde
2007-03-07  0:30             ` Kevin Ryde
2007-03-07  4:45               ` Kevin Ryde
2007-03-07  9:40               ` Ludovic Courtès
2007-02-26 23:27     ` Kevin Ryde
2007-02-28  9:47       ` Ludovic Courtès [this message]
2007-02-28 20:59         ` Kevin Ryde
2007-03-01 10:44           ` Ludovic Courtès
2007-03-05 23:15             ` Kevin Ryde
2007-08-07 16:01               ` Ludovic Courtès
2007-05-13 17:13       ` `scm_std_select ()' call in `fport_wait_for_input ()' Ludovic Courtès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87fy8qlik1.fsf@laas.fr \
    --to=ludovic.courtes@laas.fr \
    --cc=guile-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).