From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Chris Vine Newsgroups: gmane.lisp.guile.user Subject: Re: Passing objects between threads Date: Sat, 10 Sep 2016 15:30:06 +0100 Message-ID: <20160910153006.695295d7@bother.homenet> References: NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Trace: blaine.gmane.org 1473517867 13746 195.159.176.226 (10 Sep 2016 14:31:07 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Sat, 10 Sep 2016 14:31:07 +0000 (UTC) To: guile-user@gnu.org Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Sat Sep 10 16:31:02 2016 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bijJ4-0002Qy-48 for guile-user@m.gmane.org; Sat, 10 Sep 2016 16:30:58 +0200 Original-Received: from localhost ([::1]:34700 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bijJ2-0000cZ-1g for guile-user@m.gmane.org; Sat, 10 Sep 2016 10:30:56 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:55050) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bijIS-0000at-MC for guile-user@gnu.org; Sat, 10 Sep 2016 10:30:21 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bijIO-0002se-Fc for guile-user@gnu.org; Sat, 10 Sep 2016 10:30:19 -0400 Original-Received: from smtpout5.wanadoo.co.uk ([80.12.242.80]:35234 helo=smtpout.wanadoo.co.uk) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bijIO-0002r1-4S for guile-user@gnu.org; Sat, 10 Sep 2016 10:30:16 -0400 Original-Received: from bother.homenet ([95.146.110.119]) by mwinf5d66 with ME id hqW61t0092acZ5b03qW6ui; Sat, 10 Sep 2016 16:30:12 +0200 X-ME-Helo: bother.homenet X-ME-Date: Sat, 10 Sep 2016 16:30:12 +0200 X-ME-IP: 95.146.110.119 Original-Received: from bother.homenet (localhost [127.0.0.1]) by bother.homenet (Postfix) with ESMTP id 9E7C9121A07 for ; Sat, 10 Sep 2016 15:30:06 +0100 (BST) In-Reply-To: X-Mailer: Claws Mail 3.13.2 (GTK+ 2.24.30; i686-pc-linux-gnu) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 80.12.242.80 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:12895 Archived-At: On Sat, 10 Sep 2016 11:37:55 +0200 Panicz Maciej Godek wrote: > Hi, > is there any easy way to create a channel (queue) that could be used > to communicate between threads? In particular, if the queue is empty, > I would like the consumer to wait until something appears in it > (pretty much like the channels in Clojure) I haven't used Clojure channels, but what you describe is a traditional blocking asynchronous queue. Since guile has POSIX condition variables they are trivial to make. Here is one simple implementation, which allows multiple writers and multiple readers. async-queue-pop! blocks a reader until something is available in the queue. If there are multiple readers, which reader awakens on any write is for the thread scheduler. A loop is included in async-queue-pop! because POSIX condition variables can spuriously wake up, so you have to test the condition (whether the queue is empty or not) on any wake up before returning. You will find loads of literature and tutorials on this pattern, using condition variables. ****************************************** (use-modules (srfi srfi-9) (ice-9 q) (ice-9 threads)) (define-record-type (_make-async-queue mutex cond q) async-queue? (mutex mutex-get) (cond cond-get) (q q-get)) (define (make-async-queue) (_make-async-queue (make-mutex) (make-condition-variable) (make-q))) (define (async-queue-pop! a-q) (let ([mutex (mutex-get a-q)]) (with-mutex mutex (let ([q (q-get a-q)]) (let loop () (if (q-empty? q) (begin (wait-condition-variable (cond-get a-q) mutex) (loop)) (deq! q))))))) (define (async-queue-push! a-q item) (with-mutex (mutex-get a-q) (enq! (q-get a-q) item)) (signal-condition-variable (cond-get a-q)))