1
1
package caching
2
2
3
3
import (
4
+ "errors"
4
5
"reflect"
5
6
"sync"
6
7
)
7
8
8
- // Item ...
9
- type Item interface {}
10
-
11
9
// Queue ...
12
10
type Queue struct {
13
- items sync.Map
14
- keys []string
15
- maxSize int64
16
- curSize int64
17
- lock sync.RWMutex
11
+ items sync.Map
12
+ keys []string
13
+ queueSize int64
14
+ queueCurrentSize int64
15
+ rwMutex sync.RWMutex
18
16
}
19
17
20
18
// NewQueue ...
21
- func NewQueue (maxSize int64 ) * Queue {
19
+ func NewQueue (queueSize int64 ) * Queue {
22
20
currentQueue := Queue {
23
- items : sync.Map {},
24
- keys : []string {},
25
- maxSize : maxSize ,
26
- curSize : 0 ,
27
- lock : sync.RWMutex {},
21
+ items : sync.Map {},
22
+ keys : []string {},
23
+ queueSize : queueSize ,
24
+ queueCurrentSize : 0 ,
25
+ rwMutex : sync.RWMutex {},
28
26
}
29
27
30
28
return & currentQueue
31
29
}
32
30
33
- // Push ...
34
- func (q * Queue ) Push ( k string , t Item ) bool {
35
- itemSize := int64 (reflect .Type .Size (t ))
36
- if itemSize > q .maxSize || k == "" {
37
- return false
31
+ // Enqueue ...
32
+ func (q * Queue ) Enqueue ( key string , value interface {}) error {
33
+ itemSize := int64 (reflect .Type .Size (value ))
34
+ if itemSize > q .queueSize || key == "" {
35
+ return errors . New ( "key is empty or queue not enough space" )
38
36
}
39
37
40
- // Clean room for new items
41
- for q .curSize + itemSize > q .maxSize {
42
- q .Pop ("" )
38
+ // Clean space for new item
39
+ for q .queueCurrentSize + itemSize > q .queueSize {
40
+ q .Dequeue ("" )
43
41
}
44
42
45
- q .lock .Lock ()
46
- q .curSize = q .curSize + int64 (reflect .Type .Size (t ))
47
- q .keys = append (q .keys , k )
48
- q .items .LoadOrStore (k , t )
49
- q .lock .Unlock ()
50
- return true
43
+ q .rwMutex .Lock ()
44
+ q .queueCurrentSize = q .queueCurrentSize + int64 (reflect .Type .Size (value ))
45
+ q .keys = append (q .keys , key )
46
+ q .items .LoadOrStore (key , value )
47
+ q .rwMutex .Unlock ()
48
+
49
+ return nil
51
50
}
52
51
53
- // Pop ...
54
- func (q * Queue ) Pop ( k string ) * Item {
52
+ // Dequeue ...
53
+ func (q * Queue ) Dequeue ( key string ) error {
55
54
if q .IsEmpty () {
56
- return nil
55
+ return errors . New ( "the queue is empty" )
57
56
}
58
57
59
- var item interface {}
60
- var exits bool
61
- var idx int
58
+ var (
59
+ item interface {}
60
+ exits bool
61
+ keyIndex int
62
+ )
62
63
63
- if k != "" {
64
- // Remove item by key
65
- item , exits = q .items .Load (k )
66
- for i , n := range q .keys {
67
- if k == n {
68
- idx = i
64
+ if key != "" {
65
+ // Load item by key
66
+ item , exits = q .items .Load (key )
67
+ for i , k := range q .keys {
68
+ if key == k {
69
+ keyIndex = i
69
70
break
70
71
}
71
72
}
72
73
} else {
73
- // Remove first item
74
- key := q .keys [0 ]
75
- item , exits = q .items .Load (key )
76
- idx = 0
77
- if ! exits {
78
- return nil
79
- }
74
+ // Load the first item
75
+ item , exits = q .items .Load (q .keys [0 ])
76
+ keyIndex = 0
80
77
}
81
78
82
- q .lock .Lock ()
83
- q .curSize = q .curSize - int64 (reflect .Type .Size (item ))
84
- q .items .Delete (k )
85
- q .keys = append (q .keys [:idx ], q .keys [idx + 1 :]... )
86
- q .lock .Unlock ()
87
- i , _ := (item ).(Item )
79
+ if ! exits {
80
+ return errors .New ("this key does not exits" )
81
+ }
88
82
89
- return & i
83
+ q .rwMutex .Lock ()
84
+ q .queueCurrentSize = q .queueCurrentSize - int64 (reflect .Type .Size (item ))
85
+ q .items .Delete (key )
86
+ q .keys = append (q .keys [:keyIndex ], q .keys [keyIndex + 1 :]... ) //Update keys slice after remove this key from items map
87
+ q .rwMutex .Unlock ()
88
+
89
+ return nil
90
90
}
91
91
92
92
// Get ...
93
- func (q * Queue ) Get (k string ) (Item , bool ) {
93
+ func (q * Queue ) Get () (interface {}, error ) {
94
94
if q .IsEmpty () {
95
- return nil , false
95
+ return nil , errors . New ( "queue is empty" )
96
96
}
97
97
98
- item , exits := q .items .Load (k )
98
+ q .rwMutex .RLock ()
99
+ key := q .keys [0 ]
100
+ item , exits := q .items .Load (key )
101
+ q .rwMutex .RUnlock ()
99
102
if ! exits {
100
- return nil , false
101
- }
102
-
103
- i , ok := (item ).(Item )
104
- if ! ok {
105
- return nil , false
103
+ return nil , errors .New ("this key does not exits" )
106
104
}
107
105
108
- return i , true
106
+ return item , nil
109
107
}
110
108
111
- // Front ...
112
- func (q * Queue ) Front () * Item {
109
+ // GetByKey ...
110
+ func (q * Queue ) GetByKey ( k string ) ( interface {}, error ) {
113
111
if q .IsEmpty () {
114
- return nil
112
+ return nil , errors . New ( "queue is empty" )
115
113
}
116
114
117
- q .lock .RLock ()
118
- key := q .keys [0 ]
119
- item , _ := q .items .Load (key )
120
- i , _ := item .(Item )
121
- q .lock .RUnlock ()
115
+ q .rwMutex .RLock ()
116
+ item , exits := q .items .Load (k )
117
+ q .rwMutex .RUnlock ()
118
+ if ! exits {
119
+ return nil , errors .New ("this key does not exits" )
120
+ }
122
121
123
- return & i
122
+ return item , nil
124
123
}
125
124
126
125
// Range ...
@@ -137,3 +136,8 @@ func (q *Queue) IsEmpty() bool {
137
136
func (q * Queue ) Size () int {
138
137
return len (q .keys )
139
138
}
139
+
140
+ // Capacity ...
141
+ func (q * Queue ) Capacity () int64 {
142
+ return q .queueCurrentSize
143
+ }
0 commit comments