Resources are loaded as binary or lisp files. A streamed resource is also planned but not yet implemented. Resources are shared and loading happens asynchronically, powered by promises. Resources are used through proxies that shares a weak pointer. When a proxy is gc'd, a finalizer is triggered using trivial-garbage to release the resource.
94 lines
3.4 KiB
Common Lisp
94 lines
3.4 KiB
Common Lisp
#|
|
|
This file is a part of stoe project.
|
|
Copyright (c) 2015 Renaud Casenave-Péré (renaud@casenave-pere.fr)
|
|
|#
|
|
|
|
(uiop:define-package :stoe/test/resources
|
|
(:use :cl :prove
|
|
:stoe/core/utils
|
|
:stoe/core/resources
|
|
:stoe/test/job-utils))
|
|
(in-package :stoe/test/resources)
|
|
|
|
(setq *random-state* (make-random-state))
|
|
(defvar *data-dir* #P".data/")
|
|
(defvar *res-array* (make-array '(10)))
|
|
|
|
(defun get-resource-path (index &optional (ext "dat"))
|
|
(merge-pathnames (make-pathname :name (format nil "~2,'0d.~a" index ext)) *data-dir*))
|
|
|
|
(defun generate-files ()
|
|
(ensure-directories-exist *data-dir*)
|
|
|
|
;; Make a bunch of files full of random binary+lisp data
|
|
(loop-with-progress "Generating files" for i below 10
|
|
do (let ((data (loop for j below (* 1024 1024 (+ 0.5 (random 1.0)))
|
|
collect (random 255))))
|
|
(with-open-file (stream (get-resource-path i) :direction :output
|
|
:element-type '(unsigned-byte 8)
|
|
:if-exists :supersede)
|
|
(write-sequence data stream))
|
|
(with-open-file (stream (get-resource-path i "lisp") :direction :output
|
|
:if-exists :supersede)
|
|
(write data :stream stream))
|
|
progress-step)))
|
|
|
|
(generate-files)
|
|
|
|
(stoe/core/jobs::initialize)
|
|
(stoe/core/resources::initialize)
|
|
|
|
(plan 43)
|
|
|
|
(diag "Sync load of binary files")
|
|
(dotimes (i 10)
|
|
(setf (aref *res-array* i) (load-bin-resource (get-resource-path i)))
|
|
(is (res-loaded-p (res-deref (aref *res-array* i))) t
|
|
(format nil "file ~2,'0d.dat loaded in memory" i)))
|
|
|
|
(setf *res-array* (make-array '(10)))
|
|
(tg:gc :full t)
|
|
(is (hash-table-count stoe/core/resources::*resources-db*) 0 "All resources unloaded")
|
|
|
|
(dotimes (i 10)
|
|
(setf (aref *res-array* i) (load-bin-resource (get-resource-path i)))
|
|
(with-open-file (stream (get-resource-path (+ 10 i)) :direction :output
|
|
:element-type '(unsigned-byte 8) :if-exists :supersede)
|
|
(write-sequence (res-buffer (res-deref (aref *res-array* i))) stream))
|
|
(is (sb-ext:process-exit-code
|
|
(sb-ext:run-program "diff" (list (pathname-path (get-resource-path i))
|
|
(pathname-path (get-resource-path (+ 10 i))))
|
|
:search t)) 0
|
|
(format nil "file ~2,'0d.dat integrity" i)))
|
|
|
|
(diag "Shared load of binary files")
|
|
(dotimes (i 10)
|
|
(let* ((proxy (load-bin-resource (get-resource-path i)))
|
|
(res (res-deref proxy)))
|
|
(is (slot-value res 'refcount) 2 (format nil "file ~2,'0d.dat has 2 refs" i))
|
|
(unload-resource proxy)
|
|
(is (slot-value res 'refcount) 1 (format nil "file ~2,'0d.dat has 1 ref" i))
|
|
(unload-resource (aref *res-array* i))))
|
|
(is (hash-table-count stoe/core/resources::*resources-db*) 0 "All resources unloaded")
|
|
|
|
(diag "Async load of binary files")
|
|
(with-new-job-thread 2
|
|
(let (promise-list readyp)
|
|
(dotimes (i 10)
|
|
(multiple-value-bind (proxy promise) (load-bin-resource (get-resource-path i))
|
|
(setf (aref *res-array* i) proxy)
|
|
(push promise promise-list)))
|
|
(bb:alet ((res-list (bb:all promise-list)))
|
|
(setf readyp t))
|
|
(sleep 5)
|
|
(is readyp t "Load 10 files asynchronically")))
|
|
|
|
(stoe/core/resources::finalize)
|
|
(setf *res-array* nil)
|
|
(tg:gc :full t)
|
|
|
|
(finalize)
|
|
|
|
(stoe/core/jobs::finalize)
|
|
|
|
(uiop:delete-directory-tree *data-dir* :validate t)
|