Skip to content

Commit 0534913

Browse files
authored
Merge pull request #47 from semihbkgr/clear
Clear function
2 parents 9300b14 + 94f916d commit 0534913

File tree

2 files changed

+49
-9
lines changed

2 files changed

+49
-9
lines changed

e2e_test.go

+24
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,30 @@ func TestIterator(t *testing.T) {
235235
}
236236
}
237237

238+
func TestClear(t *testing.T) {
239+
m := New[int, any]()
240+
for i := 0; i < 100; i++ {
241+
m.Set(i, nil)
242+
}
243+
m.Clear()
244+
if m.Len() != 0 {
245+
t.Error("map size should be zero after clear")
246+
}
247+
if m.Fillrate() != 0 {
248+
t.Error("fillrate should be zero after clear")
249+
}
250+
log := int(math.Log2(defaultSize))
251+
expectedSize := uintptr(strconv.IntSize - log)
252+
if m.metadata.Load().keyshifts != expectedSize {
253+
t.Error("keyshift is not as expected after clear")
254+
}
255+
for i := 0; i < 100; i++ {
256+
if _, ok := m.Get(i); ok {
257+
t.Error("the entries should not be existing in the map after clear")
258+
}
259+
}
260+
}
261+
238262
func TestMapParallel(t *testing.T) {
239263
max := 10
240264
dur := 2 * time.Second

map.go

+25-9
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,12 @@ type (
4646

4747
// Map implements the concurrent hashmap
4848
Map[K hashable, V any] struct {
49-
listHead *element[K, V] // Harris lock-free list of elements in ascending order of hash
50-
hasher func(K) uintptr
51-
metadata atomicPointer[metadata[K, V]] // atomic.Pointer for safe access even during resizing
52-
resizing atomicUint32
53-
numItems atomicUintptr
49+
listHead *element[K, V] // Harris lock-free list of elements in ascending order of hash
50+
hasher func(K) uintptr
51+
metadata atomicPointer[metadata[K, V]] // atomic.Pointer for safe access even during resizing
52+
resizing atomicUint32
53+
numItems atomicUintptr
54+
defaultSize uintptr
5455
}
5556

5657
// used in deletion of map elements
@@ -64,11 +65,11 @@ type (
6465
func New[K hashable, V any](size ...uintptr) *Map[K, V] {
6566
m := &Map[K, V]{listHead: newListHead[K, V]()}
6667
m.numItems.Store(0)
67-
if len(size) > 0 && size[0] != 0 {
68-
m.allocate(size[0])
69-
} else {
70-
m.allocate(defaultSize)
68+
m.defaultSize = defaultSize
69+
if len(size) > 0 && size[0] > 0 {
70+
m.defaultSize = size[0]
7171
}
72+
m.allocate(m.defaultSize)
7273
m.setDefaultHasher()
7374
return m
7475
}
@@ -350,6 +351,21 @@ func (m *Map[K, V]) Grow(newSize uintptr) {
350351
}
351352
}
352353

354+
// Clear the map by removing all entries in the map.
355+
// This operation resets the underlying metadata to its initial state.
356+
func (m *Map[K, V]) Clear() {
357+
index := make([]*element[K, V], m.defaultSize)
358+
header := (*reflect.SliceHeader)(unsafe.Pointer(&index))
359+
newdata := &metadata[K, V]{
360+
keyshifts: strconv.IntSize - log2(m.defaultSize),
361+
data: unsafe.Pointer(header.Data),
362+
index: index,
363+
}
364+
m.listHead.nextPtr.Store(nil)
365+
m.metadata.Store(newdata)
366+
m.numItems.Store(0)
367+
}
368+
353369
// SetHasher sets the hash function to the one provided by the user
354370
func (m *Map[K, V]) SetHasher(hs func(K) uintptr) {
355371
m.hasher = hs

0 commit comments

Comments
 (0)