From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Caleb Ristvedt Newsgroups: gmane.lisp.guile.user Subject: Re: Continuations in custom port: "cannot invoke continuation from this context" Date: Mon, 1 Apr 2019 02:06:16 +0000 Message-ID: References: <87wokj1v06.fsf@cune.org> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="186499"; mail-complaints-to="usenet@blaine.gmane.org" To: Stefan Israelsson Tampe , guile-user@gnu.org Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Mon Apr 01 04:07:11 2019 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hAmLr-000mJE-6n for guile-user@m.gmane.org; Mon, 01 Apr 2019 04:07:07 +0200 Original-Received: from localhost ([127.0.0.1]:42607 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hAmLq-00030Q-6L for guile-user@m.gmane.org; Sun, 31 Mar 2019 22:07:06 -0400 Original-Received: from eggs.gnu.org ([209.51.188.92]:58907) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hAmLQ-0002yg-4r for guile-user@gnu.org; Sun, 31 Mar 2019 22:06:42 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hAmLM-00034d-AW for guile-user@gnu.org; Sun, 31 Mar 2019 22:06:40 -0400 Original-Received: from mail-ot1-x32c.google.com ([2607:f8b0:4864:20::32c]:38766) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hAmLI-00031I-H3 for guile-user@gnu.org; Sun, 31 Mar 2019 22:06:34 -0400 Original-Received: by mail-ot1-x32c.google.com with SMTP id e80so7099632ote.5 for ; Sun, 31 Mar 2019 19:06:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cune-org.20150623.gappssmtp.com; s=20150623; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=RCB4qcN3U7aPqV5VKlT3kWCSILVa29741Y2OlDTmFy4=; b=O4xYnA7RsnsWfvWuPXQKq8i9bWckeyLF7N0LFZ3lAPef2SlLceuo2t97kVCM+yoeO5 1SHY5mWeeB2OWW6ezwGH6V9dDrlUEVi/H5db2a+DQoJWjQvuORFUNoG1IcQZcASBVqbE lVcts3WUFN5pCwZnPmuY9TuYOrdBrvTok0KVbk7Q9SCRIkfV7zW2utb1hx8z8JXFJ/1j rZ3eeApUf4uYuKkw+AzO5hA4SLFoQ778yEyxbURpHBdxf4Fj8z+w/7wK5IwPr9lSqsyz 2/pfcYtkDgR8s8SN3CeblBSjhCM7+KZj479WhDspi+NoCtv30N3Q4k+gtTfoIZYNn/iv OjVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=RCB4qcN3U7aPqV5VKlT3kWCSILVa29741Y2OlDTmFy4=; b=VXQdzOjosz3GZ7/8NsGx2jCnWNcmxFu7AUoCcn4HaoFFwINWNs0gPsHmLc2cJjeFvz SmkiGOO+ylyZaiUQWJAa0SZM97/NPTxv/01GGSBLm61G8Yh5pOC3YnSg56pXJ5K1kWSC fOkEYY7p3sHBqXUK2Cr43q/sJGy6X/IUXY8w5sfCDlaSEZA/wRt5tBPv3Nn8ENUpeJYu K+YN01FK1EAk+rQxUtHbZ3fQKrUlmQJomRSV2i/b3ATWAgE1hBNBzZDqwl/B5ktLiCOX H5M5+ZbqxIg6LyCsXTWEF4+ilxb0khUpYu3akWIZLxBV+6rQ8hnPdxIrydgMXXNPkPPH /4rg== X-Gm-Message-State: APjAAAW/QbuVyX8JW8I4hYtKyjRRrRNF+wYVWUA5K0Dql8Q7KFhGG5CK w8wJRlEJY9TGQ3/6GPtAFjzMI75HTZbRs1yKELKTqA== X-Google-Smtp-Source: APXvYqw+1qs+33LDzKgc4XvOfWM4zX3m6TzL6ZF/i+xQPqGB3e0+4RQD0WefvMlpoWK+uO5gKaQdDU42ueWvkAurEJg= X-Received: by 2002:a9d:7f08:: with SMTP id j8mr45151052otq.284.1554084387865; Sun, 31 Mar 2019 19:06:27 -0700 (PDT) In-Reply-To: X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::32c X-Content-Filtered-By: Mailman/MimeDel 2.1.21 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.21 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" Xref: news.gmane.org gmane.lisp.guile.user:15376 Archived-At: Any idea why it would still be going to C land even with suspendable ports installed? The manual says they're implemented in scheme for precisely this reason. On Thu, Mar 28, 2019 at 12:58 PM Stefan Israelsson Tampe < stefan.itampe@gmail.com> wrote: > I have not looked at this more carefully. But I suspect that the code is > going to C land and then enters the scheme again > via the hooks and then continuations won't work as expected. > > /Stefan > > On Thu, Mar 28, 2019 at 5:42 AM Caleb Ristvedt > wrote: > >> I have a procedure that writes to an output port, a procedure that reads >> from an input port, and some processing that I want to do in between. So >> I figured that I'd try my hand at using continuations to write a custom >> input/output port that would hook the two procedures together. The idea >> is that I would give it two initial procedures, one for writing, one for >> reading, and the read! and write! procedures would remember what the >> latest read/write parameters were and read from / write to the >> corresponding bytevectors, switching to the other procedure if there >> wasn't a bytevector associated with that side. From what I've heard, >> it's basically coroutining. >> >> But I eventually (turns out exceptions in custom ports get silently >> swallowed and turned into an attempt to close the port) discovered that >> I was getting the error "cannot invoke continuations from this >> context". The control flow went like this: >> >> 1. writer >> 2. write! >> 3. reader >> 4. read! >> 5. write! >> 6. writer >> 7. write! >> 8. exception when trying to go to read! >> >> So clearly invoking the write continuation to get from 4 to 5 worked, >> but invoking the read continuation to get from 7 to 8 didn't. That >> sounds like something I read while looking at delimited continuations: >> >> "... This is because composing a saved continuation with the current >> continuation involves relocating the stack frames that were saved from >> the old stack onto a (possibly) new position on the new stack, and Guile >> can only do this for stack frames that it created for Scheme code, not >> stack frames created by the C compiler" >> >> I was under the impression this restriction only held for delimited >> continuations, but in case I was wrong, I ran >> >> (use-modules (ice-9 suspendable-ports)) >> (install-suspendable-ports!) >> >> and it continued to fail. >> >> Here is the code I've been using, in all its hideous glory: >> >> ---------------------------------------------------------------- >> (use-modules (ice-9 suspendable-ports)) >> (use-modules (rnrs io ports)) >> (use-modules (ice-9 textual-ports)) >> (use-modules (rnrs bytevectors)) >> (install-suspendable-ports!) >> >> (let* ((the-pipe #f) >> (write-cont (lambda () (format the-pipe "Hello, world!~%"))) >> (read-cont (lambda () (write (get-line the-pipe)))) >> (read-bv #f) >> (read-len 0) >> (read-off 0) >> (write-bv #f) >> (write-len 0) >> (write-off 0)) >> (set! the-pipe (make-custom-binary-input/output-port >> "scheme-pipe" >> ;; read! >> (lambda (bv index len) >> (catch #t >> (lambda () >> (format #t "Reading ~A bytes~%" len) >> (format #t "write-len: ~A write-off: ~A write-bv: >> ~A~%" >> write-len write-off write-bv) >> ;; Stored data? >> (if (> write-len len) >> ;; Write it, return to reader >> (begin >> (format #t "Read ~A bytes, return to >> reader.~%" len) >> (bytevector-copy! write-bv write-off bv >> index len) >> (set! write-off (+ write-off len)) >> (set! write-len (- write-len len)) >> len) >> ;; Write it, return to writer >> (begin >> (format #t "Read ~A bytes, return to >> writer.~%" >> write-len) >> (when (> write-len 0) >> (bytevector-copy! write-bv write-off bv >> index >> write-len)) >> (set! read-bv bv) >> (set! read-off (+ index write-len)) >> (set! read-len (- len write-len)) >> (call/cc >> (lambda (c) >> (set! read-cont c) >> (write-cont))) >> (format #t "RETURN FROM READ!~%") >> len))) >> (lambda args >> (format #t "EXCEPTION IN READ: ~A~%" args)))) >> ;; write! >> (lambda (bv index len) >> (catch #t >> (lambda () >> (format #t "Writing ~A bytes~%" len) >> (format #t "read-len: ~A read-off: ~A~%" >> read-len read-off) >> (if (> read-len len) >> ;; Write it, return to writer >> (begin >> (format #t "Wrote ~A bytes, return to >> writer.~%" >> len) >> (bytevector-copy! bv index read-bv read-off >> len) >> (set! read-off (+ read-off len)) >> (set! read-len (- read-len len)) >> len) >> ;; Write it, return to reader >> (begin >> (format #t "Wrote ~A bytes, return to >> reader.~%" >> read-len) >> (when (> read-len 0) >> (bytevector-copy! bv index read-bv >> read-off read-len)) >> (set! write-bv bv) >> (set! write-off (+ index read-len)) >> (set! write-len (- len read-len)) >> (call/cc >> (lambda (c) >> (set! write-cont c) >> (read-cont))) >> (format #t "RETURN FROM WRITE!~%") >> len))) >> (lambda args >> (format #t "EXCEPTION IN WRITE: ~A~%" args)))) >> ;; get-position >> (lambda () >> (format #t "Tried getting pos~%")) >> ;; set-position! >> (lambda (pos) >> (format #t "Tried setting pos~%")) >> ;; close >> (lambda () >> (format #t "Tried closing~%")))) >> (setvbuf the-pipe 'none) >> (write-cont) >> (format #t "DONE WRITING!~%") >> (read-cont)) >> ---------------------------------------------------------------- >> >> But just now I noticed that if I change the reader from >> >> (get-line the-pipe) >> >> to >> >> (get-bytevector-all) >> >> it gets as far as the "DONE WRITING" message and then produces the same >> "cannot invoke continuation from this context" error. >> >> Any idea what's going wrong here? >> >> Thanks, >> >> - reepca >> >>