feat!: Drop returns bool, Put doesn't stack-overflow
#21
30
subtable.go
30
subtable.go
@@ -1,13 +1,13 @@
|
|||||||
package cuckoo
|
package cuckoo
|
||||||
|
|
||||||
// An Entry is a key-value pair.
|
// An entry is a key-value pair.
|
||||||
type Entry[K, V any] struct {
|
type entry[K, V any] struct {
|
||||||
Key K
|
key K
|
||||||
Value V
|
value V
|
||||||
}
|
}
|
||||||
|
|
||||||
type slot[K, V any] struct {
|
type slot[K, V any] struct {
|
||||||
Entry[K, V]
|
entry[K, V]
|
||||||
occupied bool
|
occupied bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ func (t *subtable[K, V]) get(key K) (value V, found bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
slot := t.slots[t.location(key)]
|
slot := t.slots[t.location(key)]
|
||||||
return slot.Value, slot.occupied && t.compare(slot.Key, key)
|
return slot.value, slot.occupied && t.compare(slot.key, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *subtable[K, V]) drop(key K) (occupied bool) {
|
func (t *subtable[K, V]) drop(key K) (occupied bool) {
|
||||||
@@ -40,7 +40,7 @@ func (t *subtable[K, V]) drop(key K) (occupied bool) {
|
|||||||
|
|
||||||
slot := &t.slots[t.location(key)]
|
slot := &t.slots[t.location(key)]
|
||||||
|
|
||||||
if slot.occupied && t.compare(slot.Key, key) {
|
if slot.occupied && t.compare(slot.key, key) {
|
||||||
slot.occupied = false
|
slot.occupied = false
|
||||||
t.size--
|
t.size--
|
||||||
return true
|
return true
|
||||||
@@ -65,34 +65,34 @@ func (t *subtable[K, V]) update(key K, value V) (updated bool) {
|
|||||||
|
|
||||||
slot := &t.slots[t.location(key)]
|
slot := &t.slots[t.location(key)]
|
||||||
|
|
||||||
if slot.occupied && t.compare(slot.Key, key) {
|
if slot.occupied && t.compare(slot.key, key) {
|
||||||
slot.Value = value
|
slot.value = value
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *subtable[K, V]) insert(insertion Entry[K, V]) (evicted Entry[K, V], eviction bool) {
|
func (t *subtable[K, V]) insert(insertion entry[K, V]) (evicted entry[K, V], eviction bool) {
|
||||||
if t.capacity == 0 {
|
if t.capacity == 0 {
|
||||||
return insertion, true
|
return insertion, true
|
||||||
}
|
}
|
||||||
|
|
||||||
slot := &t.slots[t.location(insertion.Key)]
|
slot := &t.slots[t.location(insertion.key)]
|
||||||
|
|
||||||
if !slot.occupied {
|
if !slot.occupied {
|
||||||
slot.Entry = insertion
|
slot.entry = insertion
|
||||||
slot.occupied = true
|
slot.occupied = true
|
||||||
t.size++
|
t.size++
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.compare(slot.Key, insertion.Key) {
|
if t.compare(slot.key, insertion.key) {
|
||||||
slot.Value = insertion.Value
|
slot.value = insertion.value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
insertion, slot.Entry = slot.Entry, insertion
|
insertion, slot.entry = slot.entry, insertion
|
||||||
return insertion, true
|
return insertion, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14
table.go
14
table.go
@@ -57,12 +57,12 @@ func (t *Table[K, V]) load() float64 {
|
|||||||
// insert attempts to put/update an entry in the table, without modifying the
|
// insert attempts to put/update an entry in the table, without modifying the
|
||||||
// size of the table. Returns a displaced entry and 'homeless = true' if an
|
// size of the table. Returns a displaced entry and 'homeless = true' if an
|
||||||
// entry could not be placed after exhausting evictions.
|
// entry could not be placed after exhausting evictions.
|
||||||
func (t *Table[K, V]) insert(entry Entry[K, V]) (displaced Entry[K, V], homeless bool) {
|
func (t *Table[K, V]) insert(entry entry[K, V]) (displaced entry[K, V], homeless bool) {
|
||||||
if t.tableA.update(entry.Key, entry.Value) {
|
if t.tableA.update(entry.key, entry.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.tableB.update(entry.Key, entry.Value) {
|
if t.tableB.update(entry.key, entry.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ func (t *Table[K, V]) resize(capacity uint64) bool {
|
|||||||
updated := t.resized(capacity)
|
updated := t.resized(capacity)
|
||||||
|
|
||||||
for k, v := range t.Entries() {
|
for k, v := range t.Entries() {
|
||||||
if _, failed := updated.insert(Entry[K, V]{k, v}); failed {
|
if _, failed := updated.insert(entry[K, V]{k, v}); failed {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ func (t *Table[K, V]) Has(key K) (exists bool) {
|
|||||||
// Put sets the value for a key. If it cannot be set, an error is returned.
|
// Put sets the value for a key. If it cannot be set, an error is returned.
|
||||||
func (t *Table[K, V]) Put(key K, value V) (err error) {
|
func (t *Table[K, V]) Put(key K, value V) (err error) {
|
||||||
var (
|
var (
|
||||||
entry = Entry[K, V]{key, value}
|
entry = entry[K, V]{key, value}
|
||||||
homeless bool
|
homeless bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ func (t *Table[K, V]) Entries() iter.Seq2[K, V] {
|
|||||||
return func(yield func(K, V) bool) {
|
return func(yield func(K, V) bool) {
|
||||||
for _, slot := range t.tableA.slots {
|
for _, slot := range t.tableA.slots {
|
||||||
if slot.occupied {
|
if slot.occupied {
|
||||||
if !yield(slot.Key, slot.Value) {
|
if !yield(slot.key, slot.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,7 +210,7 @@ func (t *Table[K, V]) Entries() iter.Seq2[K, V] {
|
|||||||
|
|
||||||
for _, slot := range t.tableB.slots {
|
for _, slot := range t.tableB.slots {
|
||||||
if slot.occupied {
|
if slot.occupied {
|
||||||
if !yield(slot.Key, slot.Value) {
|
if !yield(slot.key, slot.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user