From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Vincent Bernat Newsgroups: gmane.lisp.guile.user Subject: Re: guile and coroutines controlled from C Date: Mon, 30 Jul 2012 08:28:26 +0200 Message-ID: References: <877gtlvoc4.fsf@Kagami.home> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Trace: dough.gmane.org 1343629720 9151 80.91.229.3 (30 Jul 2012 06:28:40 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Mon, 30 Jul 2012 06:28:40 +0000 (UTC) Cc: guile-user@gnu.org To: Ian Price Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Mon Jul 30 08:28:40 2012 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 1SvjT5-0002Hz-SJ for guile-user@m.gmane.org; Mon, 30 Jul 2012 08:28:40 +0200 Original-Received: from localhost ([::1]:54335 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SvjT5-0007Xw-78 for guile-user@m.gmane.org; Mon, 30 Jul 2012 02:28:39 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:52788) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SvjT0-0007XM-Dn for guile-user@gnu.org; Mon, 30 Jul 2012 02:28:35 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SvjSy-0006TO-Tz for guile-user@gnu.org; Mon, 30 Jul 2012 02:28:34 -0400 Original-Received: from bart.luffy.cx ([78.47.78.131]:56698) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SvjSy-0006Ra-Fv for guile-user@gnu.org; Mon, 30 Jul 2012 02:28:32 -0400 Original-Received: from bart.luffy.cx (localhost [127.0.0.1]) by bart.luffy.cx (Postfix) with ESMTP id 0FA79141B8; Mon, 30 Jul 2012 08:28:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha1; c=simple; d=luffy.cx; h=from:to:cc :subject:references:date:in-reply-to:message-id:mime-version :content-type:content-transfer-encoding; s=postfix; bh=6v3xHtDbr ps9CoQ9LQGeM1v4NVA=; b=AOhRfy5hgWLoKlOpFefyFMit2PgEYszffn87pXSVH AISqTFVgRhhuPl5Mt3vfYC04Nk6M3XN2RDD0ca9VNvlfBD1Z2QTo/mzAJC+o4cld mRbLDcKgH58GOmqBMKGvmdECNM/UG/QKkD2ETrDmtSYrBgN9cfo72dkueoST0dKX kI= DomainKey-Signature: a=rsa-sha1; c=simple; d=luffy.cx; h=from:to:cc :subject:references:date:in-reply-to:message-id:mime-version :content-type:content-transfer-encoding; q=dns; s=postfix; b=Jjo EHsyyCJF2gIPpuOYEuutDo+4rS86RPWfFvRNjaaYjpgJi390JYxU1FHL0lc6zfmw 5bY2z2wxvbuuDfMekkQ6epW3rwZ1GsSDwUQ7LnrD8DintksKnjXxHIU1NVFGyFoW dh+7mBykMWqYu4DsHyFIHl26rZ7OP8V5LMY49I28= Original-Received: from neo.luffy.cx (freebox.luffy.cx [88.176.20.113]) by bart.luffy.cx (Postfix) with ESMTPS id B17CA14110; Mon, 30 Jul 2012 08:28:28 +0200 (CEST) Original-Received: by neo.luffy.cx (Postfix, from userid 500) id C240B67; Mon, 30 Jul 2012 08:28:26 +0200 (CEST) In-Reply-To: <877gtlvoc4.fsf@Kagami.home> (Ian Price's message of "Mon, 30 Jul 2012 05:56:43 +0100") User-Agent: Gnus/5.130006 (Ma Gnus v0.6) Emacs/24.1 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 78.47.78.131 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:9539 Archived-At: =E2=9D=A6 30 juillet 2012 06:56 CEST, Ian Price =C2=A0: >> #v+ >> (let ((v1 (do-something-blocking "arg1" "arg2")) >> (v2 (do-something-blocking "arg3" "arg4"))) >> (when (< (+ v1 v2) 10) (...))) >> #v- >> >> `do-something-blocking` is a registered function written in C. I want to >> be able to pause the execution inside this function and then resume it >> later (when I my program got the data wanted by the user). In the >> meantime, another "cooperative thread" may be executed. >> >> In Lua, this is something that can be done with coroutines which can be >> yield and resumed from C. In Guile, there are continuations but I have >> hard time to understand how this should work from C. >> >> What would be the equivalent of this in Guile? >> http://kristianrumberg.wordpress.com/2010/11/21/135/ > > So, is it a C function you want to pause and resume, or a scheme one? > Your first statement implies the former, but that example you pointed to > implies you want scheme coroutines, that are callable from C. Both > should be possible, but I'd need to do some experimentation before > providing help with the former, as I'm not entirely sure about the > interaction C and continuations in the vm. Hum. Both I think. :) I want a user to provide a scheme function that will be run several times in parallel against dozens of targets with cooperative multithreading. The user does not have to know how cooperation works. It just uses some primitives (implemented in C) that may yield control to another thread. The C application is event-driven. #v+ (grab-something-from-network device arg1 arg2) (do-some-computation-with-result) (grab-something-else-from-network device arg3 arg4) (grab-something-else device arg5) (some-computation) #v- The `grab-something-*` functions will be implemented in C. They will pause the current thread and resume it when data get available. In Python, there is something called "greenlets" that use the same concept. > As for scheme coroutines, I think Wingo does that in one of the > asynchronous IO branches, but I'm not sure if it exported for general > use. > > A quick hack, I wrote is posted below. Threads are represented by thunks > and are ran by calling said thunk. They would be called from C in the > same way as any other function. In practice, it would be cleaner to > create a new record type for these. [...] Your example is great! It fits exactly what I need. Since I am still pretty new, I need some time to understand each line but this seems a very good start for what I want to do. I just need to translate some parts in C since the event loop is here. From what I understand, only the `run` function needs to be moved in C. The remaining of the code can be hidden in functions or macros (but it would help if the `yield` part could be translated in C). Just one other question. > (define thread1 > (make-thread > (lambda (yield) > (let loop ((i 3)) > (if (zero? i) > 'done > (begin > (display "in thread 1...\n") > (yield) > (loop (- i 1)))))))) After `yield`, the routine is resumed when scheduled by the previous `run` function. In my case, yielding happened because I was waiting for data from the network. How could I return the appropriate data on resume? I could call some function that will provide the revelant data from some cache just after yield: #v+ (yield) (some-computation-with (grab-result-local-to-this-thread)) #v- However, maybe `yield` could return the result? > I hope that gives you a head start. If I've confused you more, I > can only apologise. If you aren't familiar with continuations at all,=20 > you could try reading http://tmp.barzilay.org/cont.txt Thanks for your help. I am still a bit confused but less than a day before. I just need some time to experiment a bit. --=20 panic("Aarggh: attempting to free lock with active wait queue - shoot Andy"= ); 2.0.38 /usr/src/linux/fs/locks.c