Skip to content

Commit d4a8b10

Browse files
committed
Added new Closer interface to IterCh, to allow for better control over record-sending goroutines
1 parent 636ae3d commit d4a8b10

18 files changed

+384
-217
lines changed

README.md

+8-6
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,14 @@ func main() {
5050

5151
// Select values >= lowerBound and values <= upperBound.
5252
// Loop through the values, in reverse order:
53-
if ch, ok := sm.BoundedIterCh(reversed, lowerBound, upperBound); ok {
54-
for rec := range ch {
55-
fmt.Printf("%+v\n", rec)
56-
}
57-
} else {
58-
fmt.Println("No values found that were equal to or within the given bounds.")
53+
iterCh, err := sm.BoundedIterCh(reversed, lowerBound, upperBound)
54+
if err != nil {
55+
fmt.Println(err)
56+
}
57+
defer iterCh.Close()
58+
59+
for rec := range iterCh.Records() {
60+
fmt.Printf("%+v\n", rec)
5961
}
6062
}
6163
```
File renamed without changes.

delete.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package sortedmap
22

3-
import "sort"
3+
import (
4+
"errors"
5+
"sort"
6+
)
47

58
func (sm *SortedMap) delete(key interface{}) bool {
69
if val, ok := sm.idx[key]; ok {
@@ -27,16 +30,16 @@ func (sm *SortedMap) delete(key interface{}) bool {
2730
return false
2831
}
2932

30-
func (sm *SortedMap) boundedDelete(lowerBound, upperBound interface{}) bool {
33+
func (sm *SortedMap) boundedDelete(lowerBound, upperBound interface{}) error {
3134
iterBounds := sm.boundsIdxSearch(lowerBound, upperBound)
3235
if iterBounds == nil {
33-
return false
36+
return errors.New(noValuesErr)
3437
}
3538
for i := iterBounds[0]; i <= iterBounds[1]-i; i++ {
3639
delete(sm.idx, sm.sorted[i])
3740
sm.sorted = deleteInterface(sm.sorted, i)
3841
}
39-
return true
42+
return nil
4043
}
4144

4245
// Delete removes a value from the collection, using the given key.
@@ -56,6 +59,6 @@ func (sm *SortedMap) BatchDelete(keys []interface{}) []bool {
5659

5760
// BoundedDelete removes values that are between the given values from the collection.
5861
// BoundedDelete returns true if the operation was successful, or false otherwise.
59-
func (sm *SortedMap) BoundedDelete(lowerBound, upperBound interface{}) bool {
62+
func (sm *SortedMap) BoundedDelete(lowerBound, upperBound interface{}) error {
6063
return sm.boundedDelete(lowerBound, upperBound)
6164
}

delete_test.go

+59-22
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,22 @@ func TestDelete(t *testing.T) {
1010
if err != nil {
1111
t.Fatal(err)
1212
}
13+
1314
if sm.Delete("") {
1415
t.Fatalf("Delete: %v", invalidDelete)
1516
}
17+
1618
for _, rec := range records {
1719
sm.Delete(rec.Key)
1820
}
19-
if err := verifyRecords(sm.IterCh(), false); err != nil {
21+
22+
iterCh := sm.IterCh()
23+
if err != nil {
24+
t.Fatal(err)
25+
}
26+
defer iterCh.Close()
27+
28+
if err := verifyRecords(iterCh.Records(), false); err != nil {
2029
t.Fatal(err)
2130
}
2231
}
@@ -40,7 +49,11 @@ func TestBatchDelete(t *testing.T) {
4049
t.Fatalf("BatchDelete: %v", invalidDelete)
4150
}
4251
}
43-
if err := verifyRecords(sm.IterCh(), false); err != nil {
52+
53+
iterCh := sm.IterCh()
54+
defer iterCh.Close()
55+
56+
if err := verifyRecords(iterCh.Records(), false); err != nil {
4457
t.Fatal(err)
4558
}
4659
}
@@ -58,39 +71,63 @@ func TestBoundedDelete(t *testing.T) {
5871

5972
earlierDate := time.Date(200, 1, 1, 0, 0, 0, 0, time.UTC)
6073

61-
if !sm.BoundedDelete(nil, nil) {
62-
t.Fatalf("TestBoundedDelete failed: %v", generalBoundsErr)
74+
if err := sm.BoundedDelete(nil, nil); err != nil {
75+
t.Fatal(err)
6376
}
6477

65-
if !sm.BoundedDelete(nil, time.Now()) {
66-
t.Fatalf("TestBoundedDelete failed: %v", generalBoundsErr)
78+
if err := sm.BoundedDelete(nil, time.Now()); err != nil {
79+
t.Fatal(err)
6780
}
6881

69-
if !sm.BoundedDelete(time.Now(), nil) {
70-
t.Fatalf("TestBoundedDelete failed: %v", generalBoundsErr)
71-
}
72-
if err := verifyRecords(sm.IterCh(), false); err != nil {
82+
if err := sm.BoundedDelete(time.Now(), nil); err != nil {
7383
t.Fatal(err)
7484
}
7585

76-
if !sm.BoundedDelete(earlierDate, time.Now()) {
77-
t.Fatalf("TestBoundedDelete failed: %v", generalBoundsErr)
78-
}
79-
if err := verifyRecords(sm.IterCh(), false); err != nil {
86+
func() {
87+
iterCh := sm.IterCh()
88+
defer iterCh.Close()
89+
90+
if err := verifyRecords(iterCh.Records(), false); err != nil {
91+
t.Fatal(err)
92+
}
93+
}()
94+
95+
if err := sm.BoundedDelete(earlierDate, time.Now()); err != nil {
8096
t.Fatal(err)
8197
}
8298

83-
if !sm.BoundedDelete(time.Now(), earlierDate) {
84-
t.Fatalf("TestBoundedDelete failed: %v", generalBoundsErr)
85-
}
86-
if err := verifyRecords(sm.IterCh(), false); err != nil {
99+
func() {
100+
iterCh := sm.IterCh()
101+
defer iterCh.Close()
102+
103+
if err := verifyRecords(iterCh.Records(), false); err != nil {
104+
t.Fatal(err)
105+
}
106+
}()
107+
108+
if err := sm.BoundedDelete(time.Now(), earlierDate); err != nil {
87109
t.Fatal(err)
88110
}
89111

90-
if sm.BoundedDelete(earlierDate, earlierDate) {
91-
t.Fatalf("TestBoundedDelete failed: %v", generalBoundsErr)
92-
}
93-
if err := verifyRecords(sm.IterCh(), false); err != nil {
112+
func() {
113+
iterCh := sm.IterCh()
114+
defer iterCh.Close()
115+
116+
if err := verifyRecords(iterCh.Records(), false); err != nil {
117+
t.Fatal(err)
118+
}
119+
}()
120+
121+
if err := sm.BoundedDelete(earlierDate, earlierDate); err == nil {
94122
t.Fatal(err)
95123
}
124+
125+
func() {
126+
iterCh := sm.IterCh()
127+
defer iterCh.Close()
128+
129+
if err := verifyRecords(iterCh.Records(), false); err != nil {
130+
t.Fatal(err)
131+
}
132+
}()
96133
}
File renamed without changes.

errors.go

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package sortedmap
2+
3+
const noValuesErr = "No values found that were equal to or within the given bounds."

examples/README.md

+22-13
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,6 @@ SortedMap supports three specific ways of processing iterable data:
114114

115115
```IterCh``` is a simple way of iterating over the entire set, in order.
116116

117-
Be aware that the writing goroutine cannot exit until it finishes sending all of its records. To get around this default behavior, please use ```CustomIterCh``` and set a timeout.
118-
119117
```go
120118
package main
121119

@@ -138,7 +136,10 @@ func main() {
138136
// BatchInsert the example records:
139137
sm.BatchInsert(records)
140138

141-
for rec := range sm.IterCh() {
139+
iterCh := sm.IterCh()
140+
defer iterCh.Close()
141+
142+
for rec := range iterCh.Records() {
142143
fmt.Printf("%+v\n", rec)
143144
}
144145
}
@@ -170,10 +171,14 @@ func main() {
170171
// BatchInsert the example records:
171172
sm.BatchInsert(records)
172173

173-
if ch, ok := sm.BoundedIterCh(false, time.Time{}, time.Now()); ok {
174-
for rec := range ch {
175-
fmt.Printf("%+v\n", rec)
176-
}
174+
iterCh, err := sm.BoundedIterCh(false, time.Time{}, time.Now())
175+
if err != nil {
176+
fmt.Println(err)
177+
}
178+
defer iterCh.Close()
179+
180+
for rec := range iterCh.Records() {
181+
fmt.Printf("%+v\n", rec)
177182
}
178183
}
179184
```
@@ -211,10 +216,14 @@ func main() {
211216
Reversed: true,
212217
}
213218

214-
if ch, ok := sm.CustomIterCh(params); ok {
215-
for rec := range ch {
216-
fmt.Printf("%+v\n", rec)
217-
}
219+
iterCh, err := sm.CustomIterCh(false, time.Time{}, time.Now())
220+
if err != nil {
221+
fmt.Println(err)
222+
}
223+
defer iterCh.Close()
224+
225+
for rec := range iterCh.Records() {
226+
fmt.Printf("%+v\n", rec)
218227
}
219228
}
220229
```
@@ -385,8 +394,8 @@ func main() {
385394
sm.BatchInsert(records)
386395

387396
// Delete values equal to or within the given bound values.
388-
if !sm.BoundedDelete(time.Time{}, time.Now()) {
389-
fmt.Println("No values fall within the specified bounds.")
397+
if err := sm.BoundedDelete(time.Time{}, time.Now()); err != nil {
398+
fmt.Println(err)
390399
}
391400
}
392401
```

get_test.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@ func TestGet(t *testing.T) {
77
if err != nil {
88
t.Fatal(err)
99
}
10+
1011
for i := range records {
1112
if val, ok := sm.Get(records[i].Key); val == nil || !ok {
1213
t.Fatalf("TestGet failed: %v", notFoundErr)
1314
}
1415
}
15-
if err := verifyRecords(sm.IterCh(), false); err != nil {
16+
17+
iterCh := sm.IterCh()
18+
defer iterCh.Close()
19+
20+
if err := verifyRecords(iterCh.Records(), false); err != nil {
1621
t.Fatal(err)
1722
}
1823
}
@@ -22,13 +27,18 @@ func TestBatchGet(t *testing.T) {
2227
if err != nil {
2328
t.Fatal(err)
2429
}
30+
2531
values, results := sm.BatchGet(keys)
2632
for i, ok := range results {
2733
if values[i] == nil || !ok {
2834
t.Fatalf("TestBatchGet failed: %v", notFoundErr)
2935
}
3036
}
31-
if err := verifyRecords(sm.IterCh(), false); err != nil {
37+
38+
iterCh := sm.IterCh()
39+
defer iterCh.Close()
40+
41+
if err := verifyRecords(iterCh.Records(), false); err != nil {
3242
t.Fatal(err)
3343
}
3444
}

has_test.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@ func TestHas(t *testing.T) {
77
if err != nil {
88
t.Fatal(err)
99
}
10+
1011
for i := range records {
1112
if !sm.Has(records[i].Key) {
1213
t.Fatalf("TestHas failed: %v", notFoundErr)
1314
}
1415
}
15-
if err := verifyRecords(sm.IterCh(), false); err != nil {
16+
17+
iterCh := sm.IterCh()
18+
defer iterCh.Close()
19+
20+
if err := verifyRecords(iterCh.Records(), false); err != nil {
1621
t.Fatal(err)
1722
}
1823
}
@@ -22,12 +27,17 @@ func TestBatchHas(t *testing.T) {
2227
if err != nil {
2328
t.Fatal(err)
2429
}
30+
2531
for _, ok := range sm.BatchHas(keys) {
2632
if !ok {
2733
t.Fatalf("TestBatchHas failed: %v", notFoundErr)
2834
}
2935
}
30-
if err := verifyRecords(sm.IterCh(), false); err != nil {
36+
37+
iterCh := sm.IterCh()
38+
defer iterCh.Close()
39+
40+
if err := verifyRecords(iterCh.Records(), false); err != nil {
3141
t.Fatal(err)
3242
}
3343
}

insert.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package sortedmap
22

3-
import "fmt"
3+
import (
4+
"errors"
5+
"fmt"
6+
)
47

58
func (sm *SortedMap) insert(key, val interface{}) bool {
69
if _, ok := sm.idx[key]; !ok {
@@ -59,6 +62,6 @@ func (sm *SortedMap) BatchInsertMap(v interface{}) error {
5962
return sm.batchInsertMapStringKeys(m)
6063

6164
default:
62-
return fmt.Errorf("%s", unsupportedTypeErr)
65+
return errors.New(unsupportedTypeErr)
6366
}
6467
}

0 commit comments

Comments
 (0)