r10944: update standards version
[kmrcl.git] / macros.lisp
index 835c6d91bcac3cffabaf49d425fe1a623a02c1d6..d0ba63c629d8e698cc011c6072ce82c20e7d604d 100644 (file)
      ,@body))
 
 
+(defmacro time-seconds (&body body)
+  (let ((t1 (gensym)))
+    `(let ((,t1 (get-internal-real-time)))
+       (values
+       (progn ,@body)
+       (coerce (/ (- (get-internal-real-time) ,t1)
+                  internal-time-units-per-second)
+               'double-float)))))
+  
 (defmacro time-iterations (n &body body)
   (let ((i (gensym))
        (count (gensym)))
       ,@(when docp
              `((setf (documentation ',var 'variable) ,doc)))
       (define-symbol-macro ,var ,backing-var))))
+
+(defmacro def-cached-vector (name element-type)
+  (let ((get-name (concat-symbol "get-" name "-vector"))
+       (release-name (concat-symbol "release-" name "-vector"))
+       (table-name (concat-symbol "*cached-" name "-table*"))
+       (lock-name (concat-symbol "*cached-" name "-lock*")))
+    `(eval-when (:compile-toplevel :load-toplevel :execute)
+       (defvar ,table-name (make-hash-table :test 'equal))
+       (defvar ,lock-name (kmrcl::make-lock ,name))
+        
+        (defun ,get-name (size)
+          (kmrcl::with-lock-held (,lock-name)
+            (let ((buffers (gethash (cons size ,element-type) ,table-name)))
+              (if buffers
+                  (let ((buffer (pop buffers)))
+                    (setf (gethash (cons size ,element-type) ,table-name) buffers)
+                    buffer)
+                (make-array size :element-type ,element-type)))))
+        
+        (defun ,release-name (buffer)
+          (kmrcl::with-lock-held (,lock-name)
+            (let ((buffers (gethash (cons (array-total-size buffer)
+                                          ,element-type)
+                                    ,table-name)))
+              (setf (gethash (cons (array-total-size buffer)
+                                   ,element-type) ,table-name)
+                (cons buffer buffers))))))))
+
+(defmacro def-cached-instance (name)
+  (let* ((new-name (concat-symbol "new-" name "-instance"))
+        (release-name (concat-symbol "release-" name "-instance"))
+        (cache-name (concat-symbol "*cached-" name "-instance-table*"))
+        (lock-name (concat-symbol "*cached-" name "-instance-lock*")))
+    `(eval-when (:compile-toplevel :load-toplevel :execute)
+       (defvar ,cache-name nil)
+       (defvar ,lock-name (kmrcl::make-lock ',name))
+        
+        (defun ,new-name ()
+          (kmrcl::with-lock-held (,lock-name)
+            (if ,cache-name
+                (pop ,cache-name)
+                (make-instance ',name))))
+        
+        (defun ,release-name (instance)
+          (kmrcl::with-lock-held (,lock-name)
+            (push instance ,cache-name))))))
+
+(defmacro with-ignore-errors (&rest forms)
+  `(progn
+     ,@(mapcar
+       (lambda (x) (list 'ignore-errors x))
+       forms)))
+
+(defmacro ppmx (form)
+  "Pretty prints the macro expansion of FORM."
+  `(let* ((exp1 (macroexpand-1 ',form))
+         (exp (macroexpand exp1))
+         (*print-circle* nil))
+     (cond ((equal exp exp1)
+           (format t "~&Macro expansion:")
+           (pprint exp))
+          (t (format t "~&First step of expansion:")
+             (pprint exp1)
+             (format t "~%~%Final expansion:")
+             (pprint exp)))
+     (format t "~%~%")
+     (values)))
+
+(defmacro defconstant* (sym value &optional doc)
+  "Ensure VALUE is evaluated only once."
+   `(defconstant ,sym (if (boundp ',sym)
+                         (symbol-value ',sym)
+                         ,value)
+     ,@(when doc (list doc))))
+
+(defmacro defvar-unbound (sym &optional (doc ""))
+    "defvar with a documentation string."
+    `(progn
+      (defvar ,sym)
+      (setf (documentation ',sym 'variable) ,doc)))
+