v2 / vlib / v / tests / generics / generics_map_with_reference_arg_test.v
92 lines · 82 sloc · 1.56 KB · 227dbc7d4a3943fe8f1541f595b6ef9851bef552
Raw
1import datatypes
2import time
3
4struct Entry[V] {
5mut:
6 value V
7 load_time u32
8}
9
10struct Lru[T, V] {
11mut:
12 m map[T]Entry[V]
13 list datatypes.DoublyLinkedList[T]
14 cap u32 = 1000
15 ttl u32 = 3
16 on_del ?fn (T, V)
17pub mut:
18 hits u32
19 miss u32
20}
21
22pub fn new[T, V](cap u32, ttl u32) &Lru[T, V] {
23 return &Lru[T, V]{
24 cap: cap
25 ttl: ttl
26 }
27}
28
29pub fn (mut l Lru[T, V]) set_on_del(on_del fn (T, V)) {
30 l.on_del = on_del
31}
32
33pub fn (mut l Lru[T, V]) add(k T, v V) {
34 if l.m.len >= (l.cap * 97 / 100) {
35 l.remove_expired(0)
36 for l.m.len > (l.cap * 90 / 100) {
37 l.del(l.list.pop_back() or { return })
38 }
39 }
40 l.m[k] = Entry[V]{v, u32(time.now().unix())}
41 l.list.push_front(k)
42}
43
44pub fn (mut l Lru[T, V]) get(k T) ?V {
45 l.remove_expired(0)
46 if k in l.m {
47 l.list.delete(l.list.index(k) or { return none })
48 l.list.push_front(k)
49 l.hits++
50 return (l.m[k] or { return none }).value
51 }
52 l.miss++
53 return none
54}
55
56pub fn (mut l Lru[T, V]) remove_expired(cnt int) {
57 now := u32(time.now().unix())
58 iter := l.list.back_iterator()
59 del_cnt := 0
60 for key in iter {
61 if e := l.m[key] {
62 if e.load_time + l.ttl >= now || (cnt > 0 && del_cnt >= cnt) {
63 break
64 }
65 l.del(key)
66 }
67 }
68}
69
70pub fn (mut l Lru[T, V]) del(k T) {
71 if k in l.m {
72 val := (l.m[k] or { return }).value
73 l.m.delete(k)
74 l.list.delete(l.list.index(k) or { -1 })
75 on_del := l.on_del or { return }
76 on_del(k, val)
77 }
78}
79
80struct TT {
81 age int
82 dd int
83}
84
85fn test_generic_map_with_reference_arg() {
86 mut c := new[int, &TT](10, 3)
87 c.add(1, &TT{2, 2})
88 ret := c.get(1)?
89 println(ret)
90 assert ret.age == 2
91 assert ret.dd == 2
92}
93