Skip to content

Commit d2d8d44

Browse files
committed
Adding documentation and example about thread safety.
Note that lookups (when there's no concurrent deletes/inserts) are thread safe.
1 parent 721a5f3 commit d2d8d44

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,5 @@ func Example() {
5858
```
5959

6060
For more examples, see [the example tests](https://github.com/panmari/cuckoofilter/blob/master/example_test.go).
61+
Operations on a filter are not thread safe by default.
62+
See [this example](example_threadsafe_test.go) for using the filter concurrently.

example_threadsafe_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package cuckoo_test
2+
3+
import (
4+
"fmt"
5+
"sync"
6+
7+
cuckoo "github.com/panmari/cuckoofilter"
8+
)
9+
10+
// Small wrapper around cuckoo filter making it thread safe.
11+
type threadSafeFilter struct {
12+
cf *cuckoo.Filter
13+
mu sync.RWMutex
14+
}
15+
16+
func (f *threadSafeFilter) insert(item []byte) {
17+
// Concurrent inserts need a Write lock.
18+
f.mu.Lock()
19+
defer f.mu.Unlock()
20+
f.cf.Insert(item)
21+
}
22+
23+
func (f *threadSafeFilter) lookup(item []byte) bool {
24+
// Concurrent lookups need a read lock.
25+
f.mu.RLock()
26+
defer f.mu.RUnlock()
27+
return f.cf.Lookup(item)
28+
}
29+
30+
func Example_threadSafe() {
31+
cf := &threadSafeFilter{
32+
cf: cuckoo.NewFilter(1000),
33+
}
34+
35+
var wg sync.WaitGroup
36+
// Insert items concurrently...
37+
for i := byte(0); i < 50; i++ {
38+
wg.Add(1)
39+
go func(item byte) {
40+
defer wg.Done()
41+
cf.insert([]byte{item})
42+
}(i)
43+
}
44+
45+
// ...while also doing lookups concurrently.
46+
for i := byte(0); i < 100; i++ {
47+
wg.Add(1)
48+
go func(item byte) {
49+
defer wg.Done()
50+
// State is not well-defined here, so we can't define expectations.
51+
cf.lookup([]byte{item})
52+
}(i)
53+
}
54+
wg.Wait()
55+
56+
// Simple lookups to verify initialization.
57+
fmt.Println(cf.lookup([]byte{1}))
58+
fmt.Println(cf.lookup([]byte{99}))
59+
60+
// Output:
61+
// true
62+
// false
63+
}

0 commit comments

Comments
 (0)