From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Mark H Weaver Newsgroups: gmane.lisp.guile.user Subject: Re: asynchronous socket library Date: Sat, 24 Aug 2013 17:33:05 -0400 Message-ID: <87d2p2bwq6.fsf@tines.lan> References: <8761w9n2i6.fsf@mark-desktop.PK5001Z> <8738rd1wwy.fsf@tines.lan> <87a9ll9loc.fsf@markwitmer.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1377380026 16021 80.91.229.3 (24 Aug 2013 21:33:46 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 24 Aug 2013 21:33:46 +0000 (UTC) Cc: guile-user@gnu.org To: mark@markwitmer.com Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Sat Aug 24 23:33:47 2013 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VDLSs-0001WI-Sb for guile-user@m.gmane.org; Sat, 24 Aug 2013 23:33:47 +0200 Original-Received: from localhost ([::1]:43954 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VDLSs-00031L-GZ for guile-user@m.gmane.org; Sat, 24 Aug 2013 17:33:46 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:40721) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VDLSf-000315-JS for guile-user@gnu.org; Sat, 24 Aug 2013 17:33:38 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VDLSa-0001GI-AN for guile-user@gnu.org; Sat, 24 Aug 2013 17:33:33 -0400 Original-Received: from world.peace.net ([96.39.62.75]:39510) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VDLSa-0001FF-5n for guile-user@gnu.org; Sat, 24 Aug 2013 17:33:28 -0400 Original-Received: from 209-6-91-212.c3-0.smr-ubr1.sbo-smr.ma.cable.rcn.com ([209.6.91.212] helo=tines.lan) by world.peace.net with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.72) (envelope-from ) id 1VDLSR-0003kH-1l; Sat, 24 Aug 2013 17:33:19 -0400 In-Reply-To: <87a9ll9loc.fsf@markwitmer.com> (mark@markwitmer.com's message of "Wed, 17 Jul 2013 09:49:07 -0700") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 96.39.62.75 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Original-Sender: guile-user-bounces+guile-user=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.user:10683 Archived-At: Hi Mark, Sorry for taking so long to respond. mark@markwitmer.com writes: > Mark H Weaver writes: > >> mark@markwitmer.com writes: >>> Reading and writing to a socket seems to lend itself well to custom >>> binary ports, >> >> Why do you say that? For most purposes, Guile's native file ports are >> superior, and they seem the natural choice for sockets. >> > > I over-generalized. In my application, I'm using the X protocol, which > is a binary one. I've been so involved with that I forgot that much of > the time you want to read/write character data from a socket. Guile's native file ports (which also work on sockets) can be used for binary data as well as character data. There's no need to create a custom binary port for this purpose. Indeed, the custom ports have several major disadvantages compared to the native file ports. >> 'get-bytevector-some' from (rnrs io ports) might do what you need. If >> there's at least one byte available it will not block, but in practice >> it reads much more than that (for buffered ports). Guile 2.0.9 has a >> nice fast implementation. Prior to 2.0.9, it was less so. >> >> In more detail: as of 2.0.9, 'get-bytevector-some' will simply copy the >> input buffer managed by Guile into a bytevector and return it. If >> Guile's input buffer is empty, it will try to refill the buffer using >> the port type's 'fill_input' method. For file ports this is >> fports.c:fport_fill_input, and for custom binary ports it's >> r6rs-ports.c:cbip_fill_input. > > In order to know if the port has at least one byte ready, you need to be > able to call 'char-ready?', don't you? And as you mentioned, that > doesn't work on custom binary ports. I'm still exploring this part of > Guile so I might not have the details right. > >> >> So again I ask, why use custom binary ports for sockets? >> > > Thanks for the detailed explanation; I think I'll move away from > them. Were they added just to meet the r6rs spec? Are there any good > uses for custom binary ports that you're aware of? Yes, custom ports are needed if the data that's being read is not coming from a file, pipe, device, socket, string, or bytevector (the cases covered by Guile's existing native port types; maybe I'm forgetting some). Similarly for writing. For example, suppose you wanted a make an input port that reads keypresses from a GUI interface. In this case, the keypresses are received via events during the main event loop. There is no underlying POSIX file descriptor to read from, nor is there a single Scheme string or bytevector. You could use pipes I suppose, but that assumes POSIX. Another way is to make a custom port. In the case of guile-xcb, I see two places where custom ports are used in auth.scm. Here's the first case: --8<---------------cut here---------------start------------->8--- (define auth-file (open-file (getenv "XAUTHORITY") "rb")) (define port (make-custom-binary-input-port "xcb-auth-input" (lambda (bv start count) (do ((n 0 (1+ n)) (ch (read-char auth-file) (read-char auth-file))) ((or (>= n count) (eof-object? ch)) n) (bytevector-u8-set! bv (+ start n) (char->integer ch)))) #f #f (lambda () (close-port port)))) --8<---------------cut here---------------end--------------->8--- First of all, that '(close-port port)' is wrong. Here you are trying to tell Guile how to close 'port', and this just recurses. I guess it should be (close-port auth-file)'. However, I don't see why this custom port is needed at all. You've already opened 'auth-file' in binary mode, so you should be able to use it directly, i.e. replace the above code with: (define port (open-file (getenv "XAUTHORITY") "rb")) The other case is here (also in auth.scm): --8<---------------cut here---------------start------------->8--- (define (read! bv start count) (let* ((in-bv (make-bytevector count)) (bytes-read (recv! sock in-bv))) (bytevector-copy! in-bv 0 bv start bytes-read) bytes-read)) (define port (make-custom-binary-input-port "xcb-input" read! #f #f #f)) --8<---------------cut here---------------end--------------->8--- Again, I don't see why this custom port should be needed. You should be able to use 'sock' directly. Anyway, thanks for working on this! :) Regards, Mark