-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsync_bm_set.go
122 lines (109 loc) · 2 KB
/
sync_bm_set.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
118
119
120
121
122
package bm_set
import "sync"
type BMSyncSet struct {
masks []uint64
zero bool
sync.RWMutex
}
type SyncSetI interface {
sync.Locker
Set(i int)
Get(i int) bool
Delete(i int)
Intersect(oth *BMSyncSet) SyncSetI
Union(oth *BMSyncSet) SyncSetI
}
func NewSync(size uint64) SyncSetI {
c := size / 64
if size%64 != 0 {
c++
}
return &BMSyncSet{
masks: make([]uint64, c),
}
}
func (s *BMSyncSet) Set(i int) {
s.Lock()
defer s.Unlock()
if i == 0 {
s.zero = true
return
}
bn, k := s.getSettings(i)
s.masks[bn] = s.masks[bn] | k
}
func (s *BMSyncSet) Get(i int) bool {
s.RLock()
defer s.RUnlock()
if i == 0 {
return s.zero
}
bn, k := s.getSettings(i)
return s.masks[bn]&k != 0
}
func (s *BMSyncSet) Delete(i int) {
s.Lock()
defer s.Unlock()
if i == 0 {
s.zero = false
return
}
bn, k := s.getSettings(i)
s.masks[bn] = s.masks[bn] & (^k)
}
func (s *BMSyncSet) getSettings(i int) (int, uint64) {
bn := i / 64
if i%64 != 0 {
bn++
}
if bn > 0 {
bn--
}
return bn, uint64(1 << (i % 64))
}
func (s *BMSyncSet) Intersect(oth *BMSyncSet) SyncSetI {
oth.RLock()
s.RLock()
defer func() {
oth.RUnlock()
s.RUnlock()
}()
ll := len(oth.masks)
if len(s.masks) > ll {
ll = len(s.masks)
}
masks := make([]uint64, ll)
for i := 0; i < ll; i++ {
if i < len(s.masks) && i < len(oth.masks) {
masks[i] = s.masks[i] | oth.masks[i]
} else if i < len(s.masks) {
masks[i] = s.masks[i]
} else if i < len(oth.masks) {
masks[i] = oth.masks[i]
}
}
if s.zero || oth.zero {
return &BMSyncSet{zero: true, masks: masks}
}
return &BMSyncSet{zero: false, masks: masks}
}
func (s *BMSyncSet) Union(oth *BMSyncSet) SyncSetI {
oth.RLock()
s.RLock()
defer func() {
oth.RUnlock()
s.RUnlock()
}()
ll := len(oth.masks)
if len(s.masks) < ll {
ll = len(s.masks)
}
masks := make([]uint64, ll)
for i := 0; i < ll; i++ {
masks[i] = s.masks[i] & oth.masks[i]
}
if s.zero && oth.zero {
return &BMSyncSet{zero: true, masks: masks}
}
return &BMSyncSet{zero: false, masks: masks}
}