| 1 | ;;;-*- Mode: Lisp; Package: Wood -*-
|
|---|
| 2 |
|
|---|
| 3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|---|
| 4 | ;;
|
|---|
| 5 | ;; q.lisp
|
|---|
| 6 | ;; A simple fifo queue. Why isn't this part of Common Lisp
|
|---|
| 7 | ;;
|
|---|
| 8 | ;; Portions Copyright © 2006 Clozure Associates and Anvita eReference (www.Anvita.info)
|
|---|
| 9 | ;; Copyright © 1996 Digitool, Inc.
|
|---|
| 10 | ;; Copyright © 1992-1995 Apple Computer, Inc.
|
|---|
| 11 | ;; All rights reserved.
|
|---|
| 12 | ;; Permission is given to use, copy, and modify this software provided
|
|---|
| 13 | ;; that Digitool is given credit in all derivative works.
|
|---|
| 14 | ;; This software is provided "as is". Digitool makes no warranty or
|
|---|
| 15 | ;; representation, either express or implied, with respect to this software,
|
|---|
| 16 | ;; its quality, accuracy, merchantability, or fitness for a particular
|
|---|
| 17 | ;; purpose.
|
|---|
| 18 |
|
|---|
| 19 | ;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|---|
| 20 | ;;
|
|---|
| 21 | ;; Modification History
|
|---|
| 22 | ;;
|
|---|
| 23 | ;; 02/01/06 gz LispWorks port
|
|---|
| 24 | ;; ------------- 0.96
|
|---|
| 25 | ;; 08/27/96 bill Added copyright and mod history comments
|
|---|
| 26 | ;;
|
|---|
| 27 |
|
|---|
| 28 | (in-package :wood)
|
|---|
| 29 |
|
|---|
| 30 | (export '(make-q enq deq q-empty-p))
|
|---|
| 31 |
|
|---|
| 32 | #+ccl
|
|---|
| 33 | (eval-when (:compile-toplevel :execute)
|
|---|
| 34 | (require "LISPEQU")) ; ccl::%cons-pool, ccl::pool.data
|
|---|
| 35 |
|
|---|
| 36 | (defstruct q
|
|---|
| 37 | start-buf
|
|---|
| 38 | start-index
|
|---|
| 39 | end-buf
|
|---|
| 40 | end-index)
|
|---|
| 41 |
|
|---|
| 42 | (defmethod print-object ((q q) stream)
|
|---|
| 43 | (print-unreadable-object (q stream :type t :identity t)
|
|---|
| 44 | ))
|
|---|
| 45 |
|
|---|
| 46 | (defconstant $q-buf-size 512)
|
|---|
| 47 | #+Lispworks (defconstant $max-num-q-bufs 20)
|
|---|
| 48 |
|
|---|
| 49 | (defvar *q-bufs*
|
|---|
| 50 | #+ccl (ccl::%cons-pool)
|
|---|
| 51 | #+LispWorks (let ((arr (make-array $max-num-q-bufs)))
|
|---|
| 52 | (hcl:set-array-weak arr t)
|
|---|
| 53 | arr))
|
|---|
| 54 |
|
|---|
| 55 | (defvar *q-bufs-lock*
|
|---|
| 56 | (bt:make-recursive-lock "*q-bufs*"))
|
|---|
| 57 |
|
|---|
| 58 | (defmacro with-qbufs-locked (() &body body)
|
|---|
| 59 | `(bt:with-recursive-lock-held (*q-bufs-lock*)
|
|---|
| 60 | ,@body))
|
|---|
| 61 |
|
|---|
| 62 | (defun make-q-buf ()
|
|---|
| 63 | (with-qbufs-locked ()
|
|---|
| 64 | #+ccl
|
|---|
| 65 | (let ((buf (ccl::pool.data *q-bufs*)))
|
|---|
| 66 | (if buf
|
|---|
| 67 | (progn
|
|---|
| 68 | (setf (ccl::pool.data *q-bufs*) (svref buf 0))
|
|---|
| 69 | (dotimes (i $q-buf-size)
|
|---|
| 70 | (setf (svref buf i) nil))
|
|---|
| 71 | buf)
|
|---|
| 72 | (make-array $q-buf-size)))
|
|---|
| 73 | #+LispWorks
|
|---|
| 74 | (let ((pos (position-if-not #'null *q-bufs*)))
|
|---|
| 75 | (if pos
|
|---|
| 76 | (let ((buf (aref *q-bufs* pos)))
|
|---|
| 77 | (setf (aref *q-bufs* pos) nil)
|
|---|
| 78 | (fill buf nil)
|
|---|
| 79 | buf)
|
|---|
| 80 | (make-array $q-buf-size)))))
|
|---|
| 81 |
|
|---|
| 82 | (defun free-q-buf (buf)
|
|---|
| 83 | (with-qbufs-locked ()
|
|---|
| 84 | #+ccl
|
|---|
| 85 | (setf (svref buf 0) (ccl::pool.data *q-bufs*)
|
|---|
| 86 | (ccl::pool.data *q-bufs*) buf)
|
|---|
| 87 | #+LispWorks
|
|---|
| 88 | (let ((pos (position-if #'null *q-bufs*)))
|
|---|
| 89 | (when pos
|
|---|
| 90 | (setf (aref *q-bufs* pos) buf)))
|
|---|
| 91 | nil))
|
|---|
| 92 |
|
|---|
| 93 | (defun enq (q elt)
|
|---|
| 94 | (setq q (require-type q 'q))
|
|---|
| 95 | (let ((buf (q-end-buf q))
|
|---|
| 96 | (index (q-end-index q)))
|
|---|
| 97 | (if (null buf)
|
|---|
| 98 | (setf buf (make-q-buf)
|
|---|
| 99 | (q-start-buf q) buf
|
|---|
| 100 | (q-start-index q) 1
|
|---|
| 101 | (q-end-buf q) buf
|
|---|
| 102 | (q-end-index q) (setq index 1))
|
|---|
| 103 | (when (>= index $q-buf-size)
|
|---|
| 104 | (setf (q-end-buf q)
|
|---|
| 105 | (setf buf
|
|---|
| 106 | (setf (svref buf 0) (make-q-buf)))
|
|---|
| 107 | (q-end-index q) (setq index 1))))
|
|---|
| 108 | (setf (svref buf index) elt)
|
|---|
| 109 | (setf (q-end-index q) (1+ index)))
|
|---|
| 110 | elt)
|
|---|
| 111 |
|
|---|
| 112 | (defun q-empty-p (q)
|
|---|
| 113 | (setq q (require-type q 'q))
|
|---|
| 114 | (let ((start-buf (q-start-buf q)))
|
|---|
| 115 | (or (null start-buf)
|
|---|
| 116 | (and (eq start-buf (q-end-buf q))
|
|---|
| 117 | (eql (q-start-index q)
|
|---|
| 118 | (q-end-index q))))))
|
|---|
| 119 |
|
|---|
| 120 | (defun deq (q &optional (error-if-empty t))
|
|---|
| 121 | (when (q-empty-p q)
|
|---|
| 122 | (if error-if-empty
|
|---|
| 123 | (error "Empty q: ~s" q)
|
|---|
| 124 | (return-from deq nil)))
|
|---|
| 125 | (let ((buf (q-start-buf q))
|
|---|
| 126 | (index (q-start-index q)))
|
|---|
| 127 | (prog1
|
|---|
| 128 | (svref buf index)
|
|---|
| 129 | (when (eql (incf index) $q-buf-size)
|
|---|
| 130 | (setq index 1)
|
|---|
| 131 | (unless (setf (q-start-buf q) (svref buf 0))
|
|---|
| 132 | (setf (q-end-buf q) nil))
|
|---|
| 133 | (free-q-buf buf))
|
|---|
| 134 | (setf (q-start-index q) index))))
|
|---|
| 135 |
|
|---|
| 136 | (provide "Q")
|
|---|
| 137 | ;;; 1 3/10/94 bill 1.8d247
|
|---|