-
Notifications
You must be signed in to change notification settings - Fork 14
/
simple-tvector.lisp
97 lines (79 loc) · 3.12 KB
/
simple-tvector.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
;; -*- lisp -*-
;; This file is part of STMX.
;; Copyright (c) 2013-2016 Massimiliano Ghilardi
;;
;; This library is free software: you can redistribute it and/or
;; modify it under the terms of the Lisp Lesser General Public License
;; (http://opensource.franz.com/preamble.html), known as the LLGPL.
;;
;; 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 Lisp Lesser General Public License for more details.
(in-package :stmx.util)
;;;; ** Transactional simple-vector: fixed-size one dimensional array
(deftype simple-tvector (&optional length)
"SIMPLE-TVECTOR is a transactional, one dimensional array.
It is currently a deftype, not a class or struct:
methods cannot be specialized on it."
`(simple-vector ,(or length '*)))
(defun simple-tvector (length &key (element-type t)
(initial-element 0) initial-contents)
"Create and return a new SIMPLE-TVECTOR."
(declare (type fixnum length)
(type list initial-contents)
(ignore element-type))
(let1 tvec (make-array length :element-type 'tvar :initial-element +dummy-tvar+)
(if initial-contents
(loop for i from 0 to (1- length)
for cell = initial-contents then (rest cell)
for element = (first cell) do
(setf (svref tvec i) (tvar element)))
(dotimes (i length)
(setf (svref tvec i) (tvar initial-element))))
tvec))
(declaim (inline simple-tvector-length))
(defun simple-tvector-length (tvec)
"Return the length of simple-tvector TVEC."
(declare (type simple-tvector tvec))
(length tvec))
(optimize-for-transaction*
(:inline t)
(defun tsvref (tvec index)
"Return the INDEX-th element of simple-tvector TVEC.
Works both inside and outside transactions"
(declare (type simple-tvector tvec)
(type fixnum index))
($ (svref tvec index))))
(optimize-for-transaction*
(:inline t)
;; do NOT (defun (setf tsvref) ..) because
;; thash-table needs an actual function #'set-tsvref
(defun set-tsvref (tvec index value)
"Set the INDEX-th element of simple-tvector TVEC to VALUE.
Works both inside and outside transactions"
(declare (type simple-tvector tvec)
(type fixnum index))
(setf ($ (svref tvec index)) value)))
(defsetf tsvref set-tsvref)
(defmacro do-simple-tvector ((element) tvec &body body)
"Execute BODY on each ELEMENT contained in simple-tvector TVEC.
Creates an implicit block named NIL, so (return ...) can be used
to exit early from the loop with an explicit return value."
(with-gensym var
`(loop for ,var across ,tvec
for ,element = ($ ,var) do
(progn ,@body))))
;; simple-tvector is a deftype, not a class or struct:
;; cannot specialize methods on it
#|
(defprint-object (tvec simple-tvector :identity nil)
(dotimes (i (length tvec))
(unless (zerop i)
(write-string " "))
(let1 var (svref tvec i)
(multiple-value-bind (value present?) (peek-$ var)
(if present?
(format t "~A" value)
(write-string "unbound"))))))
|#