1+ package utils
2+
3+ import (
4+ "sync"
5+ )
6+
7+ // TypedSyncMap is a wrapper of sync.Map that provides type-safe for keys and values.
8+ // No need to use type assertions every time, so you can have more time to enjoy other things like GochiUsa
9+ // If sync.Map methods returned nil, it will return the zero value of the type V.
10+ type TypedSyncMap [K , V any ] struct {
11+ syncMap * sync.Map
12+ }
13+
14+ // NewTypedSyncMap creates a new TypedSyncMap
15+ // K is key type, V is value type
16+ // It is recommended to use pointer types for V because sync.Map might return nil
17+ // If sync.Map methods really returned nil, it will return the zero value of the type V
18+ func NewTypedSyncMap [K any , V any ]() * TypedSyncMap [K , V ] {
19+ return & TypedSyncMap [K , V ]{
20+ syncMap : & sync.Map {},
21+ }
22+ }
23+
24+ // Clear deletes all the entries, resulting in an empty Map.
25+ func (m * TypedSyncMap [K , V ]) Clear () {
26+ m .syncMap .Clear ()
27+ }
28+
29+ // CompareAndDelete deletes the entry for key if its value is equal to old.
30+ // The old value must be of a comparable type.
31+ //
32+ // If there is no current value for key in the map, CompareAndDelete
33+ // returns false (even if the old value is the nil interface value).
34+ func (m * TypedSyncMap [K , V ]) CompareAndDelete (key K , old V ) (deleted bool ) {
35+ return m .syncMap .CompareAndDelete (key , old )
36+ }
37+
38+ // CompareAndSwap swaps the old and new values for key
39+ // if the value stored in the map is equal to old.
40+ // The old value must be of a comparable type.
41+ func (m * TypedSyncMap [K , V ]) CompareAndSwap (key K , old V , new V ) (swapped bool ) {
42+ return m .syncMap .CompareAndSwap (key , old , new )
43+ }
44+
45+ // Delete deletes the value for a key.
46+ func (m * TypedSyncMap [K , V ]) Delete (key K ) {
47+ m .syncMap .Delete (key )
48+ }
49+
50+ // Load returns the value stored in the map for a key, or nil if no
51+ // value is present.
52+ // The ok result indicates whether value was found in the map.
53+ func (m * TypedSyncMap [K , V ]) Load (key K ) (value V , ok bool ) {
54+ anyValue , ok := m .syncMap .Load (key )
55+ // anyValue might be nil
56+ if anyValue != nil {
57+ value = anyValue .(V )
58+ }
59+ return value , ok
60+ }
61+
62+ // LoadAndDelete deletes the value for a key, returning the previous value if any.
63+ // The loaded result reports whether the key was present.
64+ func (m * TypedSyncMap [K , V ]) LoadAndDelete (key K ) (value V , loaded bool ) {
65+ anyValue , loaded := m .syncMap .LoadAndDelete (key )
66+ if anyValue != nil {
67+ value = anyValue .(V )
68+ }
69+ return value , loaded
70+ }
71+
72+ // LoadOrStore returns the existing value for the key if present.
73+ // Otherwise, it stores and returns the given value.
74+ // The loaded result is true if the value was loaded, false if stored.
75+ func (m * TypedSyncMap [K , V ]) LoadOrStore (key K , value V ) (actual V , loaded bool ) {
76+ anyActual , loaded := m .syncMap .LoadOrStore (key , value )
77+ if anyActual != nil {
78+ actual = anyActual .(V )
79+ }
80+ return actual , loaded
81+ }
82+
83+ // Range calls f sequentially for each key and value present in the map.
84+ // If f returns false, range stops the iteration.
85+ //
86+ // Range does not necessarily correspond to any consistent snapshot of the Map's
87+ // contents: no key will be visited more than once, but if the value for any key
88+ // is stored or deleted concurrently (including by f), Range may reflect any
89+ // mapping for that key from any point during the Range call. Range does not
90+ // block other methods on the receiver; even f itself may call any method on m.
91+ //
92+ // Range may be O(N) with the number of elements in the map even if f returns
93+ // false after a constant number of calls.
94+ func (m * TypedSyncMap [K , V ]) Range (f func (key K , value V ) bool ) {
95+ m .syncMap .Range (func (key , value any ) bool {
96+ return f (key .(K ), value .(V ))
97+ })
98+ }
99+
100+ // Store sets the value for a key.
101+ func (m * TypedSyncMap [K , V ]) Store (key K , value V ) {
102+ m .syncMap .Store (key , value )
103+ }
104+
105+ // Swap swaps the value for a key and returns the previous value if any. The loaded result reports whether the key was present.
106+ func (m * TypedSyncMap [K , V ]) Swap (key K , value V ) (previous V , loaded bool ) {
107+ anyPrevious , loaded := m .syncMap .Swap (key , value )
108+ if anyPrevious != nil {
109+ previous = anyPrevious .(V )
110+ }
111+ return previous , loaded
112+ }
0 commit comments