forked from skeeto/skewer-mode
-
Notifications
You must be signed in to change notification settings - Fork 1
/
cache-table.el
67 lines (51 loc) · 2.49 KB
/
cache-table.el
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
;;; cache-table.el --- a hash table with expiring entries
;; This is free and unencumbered software released into the public domain.
;; Author: Christopher Wellons <mosquitopsu@gmail.com>
;; Version: 1.0
;;; Commentary:
;; See the docstring of `make-cache-table'. There is no
;; `put-cache-table': use `setf' on `get-cache-table' instead.
;;; Code:
(eval-when-compile (require 'cl))
(defstruct cache-table-struct
"A cache table with expiring entries. Use `make-cache-table' to
create instances of this struct."
expire-time table)
(defun make-cache-table (expire-time &rest keyword-args)
"Create a new cache-table with entries automatically removed
from the table after EXPIRE-TIME seconds. This function accepts
the same keyword arguments as `make-hash-table'. Entries are not
actually removed from the cache-table until an access is made to
the cache-table.
Use `get-cache-table' to get and put (via setf) entries."
(make-cache-table-struct :expire-time expire-time
:table (apply #'make-hash-table keyword-args)))
(defun cache-table-clear-expired (cache-table)
"Remove all expired entries from CACHE-TABLE."
(loop with expire-time = (cache-table-struct-expire-time cache-table)
with table = (cache-table-struct-table cache-table)
with dead-time = (- (float-time) expire-time)
for key being the hash-keys of table using (hash-value entry)
for (time . value) = entry
when (< time dead-time) do (remhash key table)))
(defun get-cache-table (key cache-table &optional default)
"Access the value for KEY in CACHE-TABLE if it has not yet
expired. Behaves just like `gethash'."
(cache-table-clear-expired cache-table)
(cdr (gethash key (cache-table-struct-table cache-table) (cons 0 default))))
(defsetf get-cache-table (key cache-table) (value)
"Put an entry in the hash table, like (setf (gethash key table) value)."
`(progn
(cache-table-clear-expired ,cache-table)
(puthash ,key (cons (float-time) ,value)
(cache-table-struct-table ,cache-table))))
(defun cache-table-map (f cache-table)
"Like `maphash', call F for all non-expired entries in CACHE-TABLE."
(cache-table-clear-expired cache-table)
(maphash (lambda (k v) (funcall f k (cdr v)))
(cache-table-struct-table cache-table)))
(defun cache-table-count (cache-table)
"Like `hash-table-count', count the number of non-expired entries."
(hash-table-count (cache-table-struct-table cache-table)))
(provide 'cache-table)
;;; cache-table.el ends here