1package ccache
2
3import (
4	"container/list"
5	"sync/atomic"
6	"time"
7)
8
9type Sized interface {
10	Size() int64
11}
12
13type TrackedItem interface {
14	Value() interface{}
15	Release()
16	Expired() bool
17	TTL() time.Duration
18	Expires() time.Time
19	Extend(duration time.Duration)
20}
21
22type nilItem struct{}
23
24func (n *nilItem) Value() interface{} { return nil }
25func (n *nilItem) Release()           {}
26
27func (i *nilItem) Expired() bool {
28	return true
29}
30
31func (i *nilItem) TTL() time.Duration {
32	return time.Minute
33}
34
35func (i *nilItem) Expires() time.Time {
36	return time.Time{}
37}
38
39func (i *nilItem) Extend(duration time.Duration) {
40}
41
42var NilTracked = new(nilItem)
43
44type Item struct {
45	key        string
46	group      string
47	promotions int32
48	refCount   int32
49	expires    int64
50	size       int64
51	value      interface{}
52	element    *list.Element
53}
54
55func newItem(key string, value interface{}, expires int64) *Item {
56	size := int64(1)
57	if sized, ok := value.(Sized); ok {
58		size = sized.Size()
59	}
60	return &Item{
61		key:        key,
62		value:      value,
63		promotions: 0,
64		size:       size,
65		expires:    expires,
66	}
67}
68
69func (i *Item) shouldPromote(getsPerPromote int32) bool {
70	i.promotions += 1
71	return i.promotions == getsPerPromote
72}
73
74func (i *Item) Value() interface{} {
75	return i.value
76}
77
78func (i *Item) track() {
79	atomic.AddInt32(&i.refCount, 1)
80}
81
82func (i *Item) Release() {
83	atomic.AddInt32(&i.refCount, -1)
84}
85
86func (i *Item) Expired() bool {
87	expires := atomic.LoadInt64(&i.expires)
88	return expires < time.Now().UnixNano()
89}
90
91func (i *Item) TTL() time.Duration {
92	expires := atomic.LoadInt64(&i.expires)
93	return time.Nanosecond * time.Duration(expires-time.Now().UnixNano())
94}
95
96func (i *Item) Expires() time.Time {
97	expires := atomic.LoadInt64(&i.expires)
98	return time.Unix(0, expires)
99}
100
101func (i *Item) Extend(duration time.Duration) {
102	atomic.StoreInt64(&i.expires, time.Now().Add(duration).UnixNano())
103}
104