From: Andy Wingo <wingo@pobox.com>
To: guile-devel <guile-devel@gnu.org>
Subject: ice-9 async-queue
Date: Mon, 06 Feb 2012 18:00:53 +0100 [thread overview]
Message-ID: <87d39rhp6i.fsf@pobox.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 185 bytes --]
Hi all,
I was thinking of adding the following to Guile, to eventually help make
the web server a little less terrible. What do you think? I haven't
tested it properly yet.
Andy
[-- Attachment #2: (ice-9 async-queue) --]
[-- Type: text/plain, Size: 4045 bytes --]
;;; Asynchronous queues
;; Copyright (C) 2012 Free Software Foundation, Inc.
;; This library is free software; you can redistribute it and/or
;; modify it under the terms of the GNU Lesser General Public
;; License as published by the Free Software Foundation; either
;; version 3 of the License, or (at your option) any later version.
;;
;; This library is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; Lesser General Public License for more details.
;;
;; You should have received a copy of the GNU Lesser General Public
;; License along with this library; if not, write to the Free Software
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
;; 02110-1301 USA
;;; Commentary:
;;;
;;; An implementation of thread-safe asynchronous queues, with both
;;; blocking and nonblocking interfaces.
;;;
;;; Code:
(define-module (ice-9 async-queue)
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-9 gnu)
#:use-module (ice-9 format)
#:use-module (ice-9 threads)
#:export (make-async-queue
async-queue-length async-queue-capacity
async-queue-push!
async-queue-pop! async-queue-try-pop!))
;; One thing that we should be careful about is to avoid exposing
;; information about the way this queue is implemented.
;;
;; Currently we use an array, but it's easy to imagine a functional
;; implementation facilitated by compare-and-swap operations, with
;; perhaps the option to disable the blocking interfaces (and thereby
;; remove the need for the mutex and cond var).
;;
(define-record-type <async-queue>
(make-aq mutex condvar buf length capacity read-idx)
async-queue?
(mutex aq-mutex)
(condvar aq-condvar)
(buf aq-buf)
(capacity aq-capacity)
(length aq-length set-aq-length!)
(read-idx aq-read-idx set-aq-read-idx!))
(set-record-type-printer!
<async-queue>
(lambda (aq port)
(format port "<async-queue ~x ~a/~a>" (object-address aq)
(aq-length aq) (aq-capacity aq))))
(define (aq-inc! aq)
(set-aq-length! aq (1+ (aq-length aq)))
(signal-condition-variable (aq-condvar aq)))
(define (aq-dec! aq)
(set-aq-length! aq (1- (aq-length aq)))
(signal-condition-variable (aq-condvar aq)))
(define (aq-idx aq idx)
(modulo idx (aq-capacity aq)))
(define (aq-wait aq time)
(if time
(wait-condition-variable (aq-condvar aq) (aq-mutex aq) time)
(wait-condition-variable (aq-condvar aq) (aq-mutex aq))))
(define* (make-async-queue #:key (capacity 10))
(make-aq (make-mutex)
(make-condition-variable)
(make-vector capacity #f)
capacity
0
0))
(define (async-queue-length aq)
(with-mutex (aq-mutex aq)
(aq-length aq)))
(define (async-queue-capacity aq)
(aq-capacity aq))
(define* (async-queue-push! aq item #:optional time)
(with-mutex (aq-mutex aq)
(let lp ()
(if (< (aq-length aq) (aq-capacity aq))
(let ((idx (aq-idx aq (+ (aq-read-idx aq) (aq-length aq)))))
(vector-set! (aq-buf aq) idx item)
(aq-inc! aq)
#t)
(and (aq-wait aq time) (lp))))))
(define* (async-queue-pop! aq #:optional time)
(with-mutex (aq-mutex aq)
(let lp ()
(if (zero? (aq-length aq))
(if (aq-wait aq time)
(lp)
(values #f #f))
(let* ((idx (aq-read-idx aq))
(item (vector-ref (aq-buf aq) idx)))
(vector-set! (aq-buf aq) idx #f)
(set-aq-read-idx! aq (aq-idx aq (1+ idx)))
(aq-dec! aq)
(values item #t))))))
(define* (async-queue-try-pop! aq)
(with-mutex (aq-mutex aq)
(if (zero? (aq-length aq))
(values #f #f)
(let* ((idx (aq-read-idx aq))
(item (vector-ref (aq-buf aq) idx)))
(vector-set! (aq-buf aq) idx #f)
(set-aq-read-idx! aq (aq-idx aq (1+ idx)))
(aq-dec! aq)
(values item #t)))))
[-- Attachment #3: Type: text/plain, Size: 26 bytes --]
--
http://wingolog.org/
next reply other threads:[~2012-02-06 17:00 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-06 17:00 Andy Wingo [this message]
2012-02-06 22:09 ` ice-9 async-queue Mike Gran
2012-02-07 8:34 ` Andy Wingo
2012-02-07 8:36 ` Andy Wingo
2012-02-06 22:57 ` Ludovic Courtès
2012-02-07 8:44 ` Andy Wingo
2012-02-08 13:44 ` Ludovic Courtès
2012-03-03 17:53 ` Andy Wingo
2012-03-07 21:11 ` Ludovic Courtès
2012-02-07 10:02 ` Daniel Hartwig
2012-02-07 21:46 ` Andy Wingo
2012-02-08 8:36 ` Daniel Hartwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87d39rhp6i.fsf@pobox.com \
--to=wingo@pobox.com \
--cc=guile-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).