feat!: Drop returns bool, Put doesn't stack-overflow #21

Merged
mvhutz merged 12 commits from feat/safe-put into main 2026-04-17 01:31:02 +00:00
Showing only changes of commit 24df23218c - Show all commits

View File

@@ -153,12 +153,8 @@ func (t *Table[K, V]) Has(key K) (exists bool) {
return return
} }
// 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.
// along with the last displaced entry. func (t *Table[K, V]) Put(key K, value V) (err error) {
//
// On failure, the returned entry and the current table contents together
// preserve all previously inserted entries and the attempted entry.
func (t *Table[K, V]) Put(key K, value V) (displaced Entry[K, V], err error) {
var ( var (
entry = Entry[K, V]{key, value} entry = Entry[K, V]{key, value}
homeless bool homeless bool
@@ -173,18 +169,18 @@ func (t *Table[K, V]) Put(key K, value V) (displaced Entry[K, V], err error) {
// early when the table is sparse, while the latter catches cases where // early when the table is sparse, while the latter catches cases where
// growing never helps. // growing never helps.
if t.load() < t.minLoadFactor { if t.load() < t.minLoadFactor {
return entry, fmt.Errorf("hash functions produced a cycle at load %d/%d: %w", t.Size(), t.TotalCapacity(), ErrBadHash) return fmt.Errorf("hash functions produced a cycle at load %d/%d: %w", t.Size(), t.TotalCapacity(), ErrBadHash)
} }
// It is theoretically possible to have a table with a larger capacity // It is theoretically possible to have a table with a larger capacity
// that is valid. But this chance is astronomically small, so we ignore // that is valid. But this chance is astronomically small, so we ignore
// it in this implementation. // it in this implementation.
if grew := t.grow(); !grew { if grew := t.grow(); !grew {
return entry, fmt.Errorf("could not redistribute entries into larger table: %w", ErrBadHash) return fmt.Errorf("could not redistribute entries into larger table: %w", ErrBadHash)
} }
} }
return entry, fmt.Errorf("could not place entry after %d resizes: %w", defaultGrowthLimit, ErrBadHash) return fmt.Errorf("could not place entry after %d resizes: %w", defaultGrowthLimit, ErrBadHash)
} }
// Drop removes a value for a key in the table. Returns whether the key had // Drop removes a value for a key in the table. Returns whether the key had