From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: mark@markwitmer.com Newsgroups: gmane.lisp.guile.user Subject: Re: asynchronous socket library Date: Tue, 16 Jul 2013 23:07:13 -0700 Message-ID: <8761w9n2i6.fsf@mark-desktop.PK5001Z> References: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Trace: ger.gmane.org 1374041416 24200 80.91.229.3 (17 Jul 2013 06:10:16 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 17 Jul 2013 06:10:16 +0000 (UTC) To: guile-user@gnu.org Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Wed Jul 17 08:10:18 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 1UzKwM-0004dI-0a for guile-user@m.gmane.org; Wed, 17 Jul 2013 08:10:18 +0200 Original-Received: from localhost ([::1]:45971 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UzKwL-0006nT-If for guile-user@m.gmane.org; Wed, 17 Jul 2013 02:10:17 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:53953) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UzKwC-0006m1-22 for guile-user@gnu.org; Wed, 17 Jul 2013 02:10:09 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UzKw9-0007QK-OR for guile-user@gnu.org; Wed, 17 Jul 2013 02:10:08 -0400 Original-Received: from plane.gmane.org ([80.91.229.3]:35066) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UzKw9-0007NW-If for guile-user@gnu.org; Wed, 17 Jul 2013 02:10:05 -0400 Original-Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1UzKw7-0004Wy-QV for guile-user@gnu.org; Wed, 17 Jul 2013 08:10:03 +0200 Original-Received: from 174-21-131-23.tukw.qwest.net ([174.21.131.23]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Wed, 17 Jul 2013 08:10:03 +0200 Original-Received: from mark by 174-21-131-23.tukw.qwest.net with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Wed, 17 Jul 2013 08:10:03 +0200 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 58 Original-X-Complaints-To: usenet@ger.gmane.org X-Gmane-NNTP-Posting-Host: 174-21-131-23.tukw.qwest.net User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) Cancel-Lock: sha1:Yjm/IrM8ZhT4P+Ry8srfmqeRteU= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 80.91.229.3 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:10551 Archived-At: Aleix Conchillo FlaquƩ writes: > Hi, > > I was wondering if there is (or someone is working on) an asynchronous > socket library for Guile. I was thinking in a pure scheme library (not > bindings for libevent or some other). > > Thanks, > > Aleix > > I spent some time working on nonblocking input from a socket for my X bindings. You can do it in pure Scheme if you're willing to live without epoll(): Guile includes bindings for both select() and poll() (the latter is in the undocumented (ice-9 poll) module). I used select() because it had a section in the manual; I figure it's more "official" and the docs make it easier for other people to follow the code. I'm not sure how generally applicable all of my code is since it's listening specifically for X events and replies, but the way I wait on the socket looks like this. You have to handle interrupts manually: (define (file-ready? fd) (define (do-select) (select (list fd) '() '() )) ;; ----------------------------^ [SECS] [USECS] ;; You can include an optional timeout in seconds and one in microseconds (define (on-error . args) (if (= (system-error-errno args) EINTR) '(() () ()) ;; This is what select returns when the file's unavailable (apply throw args))) (memq fd (car (catch 'system-error do-select on-error)))) (if (file-ready? fd) ... do the file operation ... ... loop or do something else instead ...) Reading and writing to a socket seems to lend itself well to custom binary ports, but then I think you're stuck with an opaque buffer -- you can't properly ask the binary port if the next read beyond one byte will block or not, since it might have stuff buffered or it might not. I'd love to be wrong about that if someone happens to know how to check for the amount remaining in a custom binary port's buffer. Because of that, my code directly uses recv! every time it wants to read from the socket, event if it just needs one byte. I don't think that approach makes for very elegant nonblocking i/o, but it's been performing well enough. You can take a look at this for some more ideas (hopefully good ones): https://github.com/mwitmer/guile-xcb/blob/prompts/xcb/xml/connection.scm -- Mark Witmer