-
Notifications
You must be signed in to change notification settings - Fork 1
/
slice.go
117 lines (103 loc) · 2.07 KB
/
slice.go
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package mtoi
import "sync"
type itemSlice struct {
Key string
Value interface{}
}
// Slice
type Slice struct {
cap int
data []interface{}
tag map[string][]int
stream chan *itemSlice
lock *sync.RWMutex
}
func NewSlice(cap int) *Slice {
if cap <= 2 {
cap = 2
}
c := &Slice{
cap: cap,
data: make([]interface{}, 0, cap),
tag: make(map[string][]int, cap),
stream: make(chan *itemSlice, cap),
lock: new(sync.RWMutex),
}
c.start()
return c
}
func (c *Slice) start() {
go func() {
for v, ok := <-c.stream; ok; v, ok = <-c.stream {
if v != nil && len(c.data) < c.cap {
c.lock.Lock()
for ; v != nil && ok; v, ok = <-c.stream {
c.data = append(c.data, v.Value)
idx, ok := c.tag[v.Key]
if !ok {
idx = make([]int, 0, 2)
}
c.tag[v.Key] = append(idx, len(c.data)-1)
if len(c.data) >= c.cap {
break
}
}
c.lock.Unlock()
}
}
}()
}
func (c *Slice) Close() {
close(c.stream)
}
func (c Slice) Size() int {
c.lock.RLock()
defer c.lock.RUnlock()
return len(c.data)
}
func (c *Slice) Clean() {
c.lock.Lock()
c.data = make([]interface{}, 0, c.cap)
c.tag = make(map[string][]int, c.cap)
c.lock.Unlock()
}
func (c *Slice) Put(k string, v interface{}) {
c.stream <- &itemSlice{k, v}
c.stream <- nil
}
func (c *Slice) MulPut() (func(k string, v interface{}), func()) {
return func(k string, v interface{}) { c.stream <- &itemSlice{k, v} },
func() { c.stream <- nil }
}
func (c Slice) Get(k string) (res []interface{}, ok bool) {
c.lock.RLock()
index, ok := c.tag[k]
if ok && len(index) != 0 {
res = make([]interface{}, len(index))
for i, idx := range index {
res[i] = c.data[idx]
}
}
c.lock.RUnlock()
return
}
func (c Slice) MulGet(k string, f func(interface{})) bool {
c.lock.RLock()
index, ok := c.tag[k]
if ok && len(index) != 0 {
for _, idx := range index {
f(c.data[idx])
}
}
c.lock.RUnlock()
return ok
}
func (c Slice) Contain(k string) bool {
c.lock.RLock()
_, ok := c.tag[k]
c.lock.RUnlock()
return ok
}
func (c Slice) Array() []interface{} {
return c.data
}