Added periodic yielding to iterators

This commit is contained in:
tidwall 2019-03-05 11:33:37 -07:00
parent 73bb118617
commit 95a5556d61
1 changed files with 35 additions and 0 deletions

View File

@ -1,6 +1,8 @@
package collection package collection
import ( import (
"runtime"
"github.com/tidwall/boxtree/d2" "github.com/tidwall/boxtree/d2"
"github.com/tidwall/btree" "github.com/tidwall/btree"
"github.com/tidwall/geojson" "github.com/tidwall/geojson"
@ -9,6 +11,9 @@ import (
"github.com/tidwall/tinybtree" "github.com/tidwall/tinybtree"
) )
// yieldStep forces the iterator to yield goroutine every N steps.
const yieldStep = 0xFF
// Cursor allows for quickly paging through Scan, Within, Intersects, and Nearby // Cursor allows for quickly paging through Scan, Within, Intersects, and Nearby
type Cursor interface { type Cursor interface {
Offset() uint64 Offset() uint64
@ -330,6 +335,9 @@ func (c *Collection) Scan(desc bool, cursor Cursor,
if count <= offset { if count <= offset {
return true return true
} }
if count&yieldStep == yieldStep {
runtime.Gosched()
}
if cursor != nil { if cursor != nil {
cursor.Step(1) cursor.Step(1)
} }
@ -361,6 +369,9 @@ func (c *Collection) ScanRange(start, end string, desc bool, cursor Cursor,
if count <= offset { if count <= offset {
return true return true
} }
if count&yieldStep == yieldStep {
runtime.Gosched()
}
if cursor != nil { if cursor != nil {
cursor.Step(1) cursor.Step(1)
} }
@ -402,6 +413,9 @@ func (c *Collection) SearchValues(desc bool, cursor Cursor,
if count <= offset { if count <= offset {
return true return true
} }
if count&yieldStep == yieldStep {
runtime.Gosched()
}
if cursor != nil { if cursor != nil {
cursor.Step(1) cursor.Step(1)
} }
@ -434,6 +448,9 @@ func (c *Collection) SearchValuesRange(start, end string, desc bool,
if count <= offset { if count <= offset {
return true return true
} }
if count&yieldStep == yieldStep {
runtime.Gosched()
}
if cursor != nil { if cursor != nil {
cursor.Step(1) cursor.Step(1)
} }
@ -468,6 +485,9 @@ func (c *Collection) ScanGreaterOrEqual(id string, desc bool,
if count <= offset { if count <= offset {
return true return true
} }
if count&yieldStep == yieldStep {
runtime.Gosched()
}
if cursor != nil { if cursor != nil {
cursor.Step(1) cursor.Step(1)
} }
@ -591,6 +611,9 @@ func (c *Collection) Within(
if count <= offset { if count <= offset {
return false, true return false, true
} }
if count&yieldStep == yieldStep {
runtime.Gosched()
}
if cursor != nil { if cursor != nil {
cursor.Step(1) cursor.Step(1)
} }
@ -607,6 +630,9 @@ func (c *Collection) Within(
if count <= offset { if count <= offset {
return true return true
} }
if count&yieldStep == yieldStep {
runtime.Gosched()
}
if cursor != nil { if cursor != nil {
cursor.Step(1) cursor.Step(1)
} }
@ -641,6 +667,9 @@ func (c *Collection) Intersects(
if count <= offset { if count <= offset {
return false, true return false, true
} }
if count&yieldStep == yieldStep {
runtime.Gosched()
}
if cursor != nil { if cursor != nil {
cursor.Step(1) cursor.Step(1)
} }
@ -657,6 +686,9 @@ func (c *Collection) Intersects(
if count <= offset { if count <= offset {
return true return true
} }
if count&yieldStep == yieldStep {
runtime.Gosched()
}
if cursor != nil { if cursor != nil {
cursor.Step(1) cursor.Step(1)
} }
@ -714,6 +746,9 @@ func (c *Collection) Nearby(
if count <= offset { if count <= offset {
return true return true
} }
if count&yieldStep == yieldStep {
runtime.Gosched()
}
if cursor != nil { if cursor != nil {
cursor.Step(1) cursor.Step(1)
} }