From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Maxim Cournoyer Newsgroups: gmane.lisp.guile.user Subject: Re: Lost input when using suspendable read-line Date: Mon, 23 Aug 2021 22:03:25 -0400 Message-ID: <87sfyztx8y.fsf@gmail.com> References: <87mtp8vmap.fsf@gmail.com> <04425a0337fa3d75f367d7e390c280ff5aa1bb1c.camel@student.tugraz.at> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="4673"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) Cc: guile-user@gnu.org To: Leo Prikler Original-X-From: guile-user-bounces+guile-user=m.gmane-mx.org@gnu.org Tue Aug 24 04:03:43 2021 Return-path: Envelope-to: guile-user@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mILmw-0000x8-IB for guile-user@m.gmane-mx.org; Tue, 24 Aug 2021 04:03:42 +0200 Original-Received: from localhost ([::1]:37468 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mILmu-0007pc-9I for guile-user@m.gmane-mx.org; Mon, 23 Aug 2021 22:03:40 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:41692) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mILmk-0007pN-J1 for guile-user@gnu.org; Mon, 23 Aug 2021 22:03:30 -0400 Original-Received: from mail-qk1-x72d.google.com ([2607:f8b0:4864:20::72d]:40483) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mILmi-0004rK-SC for guile-user@gnu.org; Mon, 23 Aug 2021 22:03:30 -0400 Original-Received: by mail-qk1-x72d.google.com with SMTP id t190so21504057qke.7 for ; Mon, 23 Aug 2021 19:03:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=iJWXoAp4KBBywhdYyvxtFnmXahhL/Wh0tPXTOYnHwa0=; b=q3mfCZnaflQBaL6uCR3AN9BfDWq6iDm++nqPsD+T6obSLE1XeRK1MdHrqaJIbhsFQH IKvh0WYj0d38i8u1H+ry3z3rFPCziQQbNlPMk7jJznCY0e0mNY7lpb4MIHda+RPCazvy d1uPT3Xqq18Il6gyowF8WOFKPDdAF/9YG/3ECbUmnDhFDoKiqjJGGy+RLPDrsRsev3sI EjNxp2dK+qv+nwI3qv40UOoMoVI2mf7AKk5vvr3sazoB9OUvZ45S0whv8ymj+iK4iqOm 7HXH8WuH9/FpJFwCz6AaWD6+8OgDknVfH1gLE4JyGeL984ffItYBuLX2LMz8HYZ0SIcI WFJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=iJWXoAp4KBBywhdYyvxtFnmXahhL/Wh0tPXTOYnHwa0=; b=SMAgWrlBJfNPC1pLrYNec7d9zV4eE/JYMSoIlxcaxdtjASb8l4nlC+V1j0uOYFZLOE IJn2AbqQCFqH+XarB3hKgIJuK2CZveaZnqhfqQAuQ2s+Gx503nJfhtmAH11Vj4o+ZTet JjnxwTo+7r8ljiIMg2uTgTppUnqmvPsh6RNF7pvyvghhnVFC8StiF5ILswsFmTEsJh+y CHgAC9y6zlMsz0jiViWF0duXuYIsqPJ6ew4FQRtS8AL3KIZ/5LyVcaRkuroKOqGpM4vO 4ngnCJVP+kGaHb4JN+/2GbdAtXltd3Y5wDycsvkNJgPFw7urPJWLsA6iBXEX8bBNTfc8 G1cA== X-Gm-Message-State: AOAM533dmNLouxlkp0ZJJEsK3emM0wbKav5DPTGInSAeDGc5IMHCuDRt RX+UN6jcmONabqUu5OKh9Nx0g3XEsJg= X-Google-Smtp-Source: ABdhPJyYJIGW0Qh2W6oXr6rYFPZQmsJu9SmktJLQ8qE1OEMWJXw0aePQw6rj+/hUdS2iu+kptQQ9RQ== X-Received: by 2002:a05:620a:1677:: with SMTP id d23mr24002341qko.353.1629770607503; Mon, 23 Aug 2021 19:03:27 -0700 (PDT) Original-Received: from hurd (dsl-10-129-227.b2b2c.ca. [72.10.129.227]) by smtp.gmail.com with ESMTPSA id 69sm10265099qke.55.2021.08.23.19.03.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Aug 2021 19:03:26 -0700 (PDT) In-Reply-To: <04425a0337fa3d75f367d7e390c280ff5aa1bb1c.camel@student.tugraz.at> (Leo Prikler's message of "Mon, 23 Aug 2021 23:45:19 +0200") Received-SPF: pass client-ip=2607:f8b0:4864:20::72d; envelope-from=maxim.cournoyer@gmail.com; helo=mail-qk1-x72d.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.23 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-mx.org@gnu.org Original-Sender: "guile-user" Xref: news.gmane.io gmane.lisp.guile.user:17691 Archived-At: Hello Leo! Leo Prikler writes: > Hi, > > Am Montag, den 23.08.2021, 00:04 -0400 schrieb Maxim Cournoyer: >> --8<---------------cut here---------------start------------->8--- >> (use-modules (ice-9 match) >> (ice-9 rdelim) >> (ice-9 suspendable-ports)) >> >> (install-suspendable-ports!) >> >> (define (read-line* port cont) >> ;; Return, as a pair, the line and the terminated delimiter >> or end-of-file >> ;; object. When a line cannot be read, return the >> '(suspended >> ;; . partial-continuation) pair, where partial-continuation >> can be >> ;; evaluated in the future when the port is ready to be read. >> (call-with-prompt 'continue >> (lambda () >> (parameterize ((current-read-waiter >> (lambda (_) >> (abort-to-prompt 'continue)))) >> (if cont >> (cont) >> (read-line port 'split)))) >> (lambda (partial-continuation) >> (cons 'suspended partial-continuation)))) >> >> (define (main) >> [...] >> (let loop ((cont #f)) >> (match (select (list (port->fdes port)) '() '()) >> (((fdes ..1) () ()) >> (let next-line ((line+delim (read-line* port cont))) >> (match line+delim >> (('suspended . partial-continuation) >> (loop partial-continuation)) >> ((line . _) >> (format #t "~a~%" line) >> (next-line (read-line* port cont))))))))))) >> >> (main) >> --8<---------------cut here---------------end--------------->8--- > This main loop appears broken. Look at the value of cont over time. > On the first few lines, before suspending, you will read all the lines > just fine. But afterwards it will be set to partial-continuation, even > if said continuation is no longer current. > > This appears to be no issue if you need less than one continuation to > finish the line, but if you need two or more, the outer continuation > will cause you to redo the inner over and over again. > > I tried to make this loop somewhat more sensible: > > (define port (car child->parent-pipe)) > (define cont (make-parameter #f)) > (define do-read > (lambda () > (match (select (list (port->fdes port)) '() '()) > (((fdes ..1) () ()) > (match (read-line* port (cont)) > (('suspended . partial-cont) > partial-cont) > ((line . _) > (format #t "~a~%" line) > #f)))))) > > (let loop ((cont? (do-read))) > (loop (parameterize ((cont cont?)) (do-read))))))) > > Here, each continuation is used exactly once, and that is to finish the > current line. With this, I typically get output of the style: > > --8<---------------cut here---------------start------------->8--- > Line 1 > [wait for it...] > Line 2 > Line 3 > Done! > Line 1 > [wait for it...] > --8<---------- > -----cut here---------------end--------------->8--- > So it's not perfect either, but it's somewhat better than what you have > currently. > > I'd hazard a guess that there are simpler implementations that need not > make use of parameters, particularly because I kinda eliminated the > inner loop anyway. A simpler fix, which retains your structure is to > use > (next-line (read-line* port #f))))))))))) > in the case where a line has already been read. This also seems to > have the desired behaviour of waiting after the "Done!" line. Thank you so much (to flatwhatson on #guile) :-). I had indeed failed to carry/refresh the partial continuity in the inner loop. I had made a similar mistake in the original problem which was capturing the continuity at the wrong place in the closure, which was fixed like so: --8<---------------cut here---------------start------------->8--- 1 file changed, 7 insertions(+), 7 deletions(-) src/mcron/base.scm | 14 +++++++------- modified src/mcron/base.scm @@ -330,8 +330,7 @@ associated instance." ;; could not be read. (let ((name (job-data:name data)) (pid (job-data:pid data)) - (port (job-data:port data)) - (cont (job-data:continuation data))) + (port (job-data:port data))) (define (read-line*) ;; Return, as a pair, the line and the terminated delimiter or end-of-file @@ -343,11 +342,12 @@ associated instance." (parameterize ((current-read-waiter (lambda (_) (abort-to-prompt 'continue)))) - (if cont - (begin - (set-job-data-continuation! data #f) ;reset continuation field - (cont)) - (read-line port 'split)))) + (let ((cont (job-data:continuation data))) + (if cont + (begin + (set-job-data-continuation! data #f) ;reset continuation + (cont)) + (read-line port 'split))))) (lambda (partial-continuation) (cons 'suspended partial-continuation)))) --8<---------------cut here---------------end--------------->8--- You've made my day. Happy hacking! Maxim