Skip to content

Commit 96bf451

Browse files
committed
docs
1 parent d162277 commit 96bf451

File tree

5 files changed

+56
-18
lines changed

5 files changed

+56
-18
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,5 @@ debug/ # Common directory for debug artifacts
6262
# Delve Debugger
6363
__debug_bin*
6464
qodana.yaml
65-
memprofile.out
66-
profile.out
65+
cmd
66+
testing

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- Memoizes functions with TTL, supporting 0 to 7 comparable parameters. [List of Memoize Functions](https://github.com/AhmedGoudaa/go_memoize/blob/main/memoize.go)
99
- High performance, zero allocation, and zero dependencies.
1010
- Utilizes the FNV-1a hash algorithm for caching.
11+
- Thread-safe and concurrent-safe.
1112

1213

1314
## Installation

cache.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@ import (
66
"time"
77
)
88

9+
// zeroValue returns the zero value for any type T.
910
func zeroValue[T any]() T {
1011
var zero T
1112
return zero
1213
}
1314

14-
// cacheGroup manages multiple caches with a shared ticker
15+
// cacheGroup manages multiple caches with a shared ticker.
1516
type cacheGroup struct {
1617
now atomic.Value
1718
ticker *time.Ticker
1819
tickInterval time.Duration
1920
done chan struct{}
2021
}
2122

22-
// NewCacheGroup creates a new cache group with shared ticker
23+
// newCacheGroup creates a new cache group with a shared ticker.
2324
func newCacheGroup() *cacheGroup {
2425
group := &cacheGroup{
2526
done: make(chan struct{}),
@@ -30,6 +31,7 @@ func newCacheGroup() *cacheGroup {
3031
return group
3132
}
3233

34+
// startTicker starts the ticker for the cache group.
3335
func (g *cacheGroup) startTicker() {
3436
g.ticker = time.NewTicker(g.tickInterval) // Initialize the ticker
3537
go func() {
@@ -45,18 +47,16 @@ func (g *cacheGroup) startTicker() {
4547
}()
4648
}
4749

48-
//func (g *cacheGroup) stop() {
49-
// close(g.done)
50-
// g.ticker = nil
51-
//}
52-
50+
// var cacheGroupInstance is a singleton instance of cacheGroup.
5351
var cacheGroupInstance = newCacheGroup()
5452

53+
// entry represents a cache entry with a value and a timestamp.
5554
type entry[V any] struct {
5655
value V
5756
timeStamp int64
5857
}
5958

59+
// Cache is a generic cache with a time-to-live (TTL) for each entry.
6060
type Cache[K comparable, V any] struct {
6161
Entries map[K]entry[V]
6262
ttl int64
@@ -65,6 +65,7 @@ type Cache[K comparable, V any] struct {
6565
zeroVal V
6666
}
6767

68+
// NewCache creates a new cache with the specified TTL.
6869
func NewCache[K comparable, V any](ttl int64) *Cache[K, V] {
6970
return &Cache[K, V]{
7071
Entries: make(map[K]entry[V]),
@@ -74,6 +75,7 @@ func NewCache[K comparable, V any](ttl int64) *Cache[K, V] {
7475
}
7576
}
7677

78+
// NewCacheSized creates a new cache with the specified size and TTL.
7779
func NewCacheSized[K comparable, V any](size int, ttl int64) *Cache[K, V] {
7880
return &Cache[K, V]{
7981
Entries: make(map[K]entry[V], size),
@@ -83,11 +85,12 @@ func NewCacheSized[K comparable, V any](size int, ttl int64) *Cache[K, V] {
8385
}
8486
}
8587

88+
// NowUnix returns the current Unix timestamp from the cache group.
8689
func (c *Cache[K, V]) NowUnix() int64 {
8790
return c.cacheGroup.now.Load().(int64)
8891
}
8992

90-
// inlined get and set
93+
// GetOrCompute retrieves the value for the given key or computes it using the provided function if not present or expired.
9194
func (c *Cache[K, V]) GetOrCompute(key K, computeFn func() V) V {
9295
c.mu.RLock()
9396
existingEntry, ok := c.Entries[key]
@@ -105,19 +108,22 @@ func (c *Cache[K, V]) GetOrCompute(key K, computeFn func() V) V {
105108
return newVal
106109
}
107110

111+
// Delete removes the entry for the given key from the cache.
108112
func (c *Cache[K, V]) Delete(key K) {
109113
c.mu.Lock()
110114
delete(c.Entries, key)
111115
c.mu.Unlock()
112116
}
113117

118+
// Set adds or updates the value for the given key in the cache.
114119
func (c *Cache[K, V]) Set(key K, value V) {
115120
timeStamp := c.NowUnix()
116121
c.mu.Lock()
117122
c.Entries[key] = entry[V]{value: value, timeStamp: timeStamp}
118123
c.mu.Unlock()
119124
}
120125

126+
// Get retrieves the value for the given key from the cache if present and not expired.
121127
func (c *Cache[K, V]) Get(key K) (V, bool) {
122128
c.mu.RLock()
123129
entry, ok := c.Entries[key]

hashing.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,34 +29,50 @@ const (
2929
falseHash = offset64 ^ 0*prime64
3030
)
3131

32+
// hash1 hashes a single key using the FNV-1a algorithm.
33+
// A is a comparable type.
3234
func hash1[A comparable](key A) uint64 {
3335
return hash(offset64, key)
3436
}
3537

38+
// hash2 hashes two keys using the FNV-1a algorithm.
39+
// A and B are comparable types.
3640
func hash2[A, B comparable](key1 A, key2 B) uint64 {
3741
return hash(hash(offset64, key1), key2)
3842
}
3943

44+
// hash3 hashes three keys using the FNV-1a algorithm.
45+
// A, B, and C are comparable types.
4046
func hash3[A, B, C comparable](key1 A, key2 B, key3 C) uint64 {
4147
return hash(hash(hash(offset64, key1), key2), key3)
4248
}
4349

50+
// hash4 hashes four keys using the FNV-1a algorithm.
51+
// A, B, C, and D are comparable types.
4452
func hash4[A, B, C, D comparable](key1 A, key2 B, key3 C, key4 D) uint64 {
4553
return hash(hash(hash(hash(offset64, key1), key2), key3), key4)
4654
}
4755

56+
// hash5 hashes five keys using the FNV-1a algorithm.
57+
// A, B, C, D, and E are comparable types.
4858
func hash5[A, B, C, D, E comparable](key1 A, key2 B, key3 C, key4 D, key5 E) uint64 {
4959
return hash(hash(hash(hash(hash(offset64, key1), key2), key3), key4), key5)
5060
}
5161

62+
// hash6 hashes six keys using the FNV-1a algorithm.
63+
// A, B, C, D, E, and F are comparable types.
5264
func hash6[A, B, C, D, E, F comparable](key1 A, key2 B, key3 C, key4 D, key5 E, key6 F) uint64 {
5365
return hash(hash(hash(hash(hash(hash(offset64, key1), key2), key3), key4), key5), key6)
5466
}
5567

68+
// hash7 hashes seven keys using the FNV-1a algorithm.
69+
// A, B, C, D, E, F, and G are comparable types.
5670
func hash7[A, B, C, D, E, F, G comparable](key1 A, key2 B, key3 C, key4 D, key5 E, key6 F, key7 G) uint64 {
5771
return hash(hash(hash(hash(hash(hash(hash(offset64, key1), key2), key3), key4), key5), key6), key7)
5872
}
5973

74+
// hash hashes a key using the FNV-1a algorithm.
75+
// A is a comparable type.
6076
func hash[A comparable](hash uint64, key A) uint64 {
6177
switch v := any(key).(type) {
6278
case string:
@@ -94,13 +110,7 @@ func hash[A comparable](hash uint64, key A) uint64 {
94110
}
95111
}
96112

97-
//func hashString(hash uint64, key string) uint64 {
98-
// for i := 0; i < len(key); i++ {
99-
// hash = (hash ^ uint64(key[i])) * prime64
100-
// }
101-
// return hash
102-
//}
103-
113+
// hashString hashes a string key using the FNV-1a algorithm.
104114
func hashString(hash uint64, key string) uint64 {
105115
length := len(key)
106116

@@ -118,22 +128,26 @@ func hashString(hash uint64, key string) uint64 {
118128
}
119129
return hash
120130
}
131+
132+
// hashInt hashes an integer key using the FNV-1a algorithm.
121133
func hashInt(hash uint64, key uint64) uint64 {
122134
return (hash ^ key) * prime64
123135
}
124136

137+
// hashUint hashes an unsigned integer key using the FNV-1a algorithm.
125138
func hashUint(hash uint64, key uint64) uint64 {
126139
return (hash ^ key) * prime64
127140
}
128141

142+
// hashFloat hashes a floating-point key using the FNV-1a algorithm.
129143
func hashFloat(hash uint64, key uint64) uint64 {
130144
return (hash ^ key) * prime64
131145
}
132146

147+
// hashBool hashes a boolean key using the FNV-1a algorithm.
133148
func hashBool(key bool) uint64 {
134149
if key {
135150
return trueHash
136151
}
137152
return falseHash
138-
139153
}

memoize.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"time"
55
)
66

7+
// Memoize returns a memoized version of the compute function with a specified TTL.
8+
// V is the type of the value returned by the compute function.
79
func Memoize[V any](computeFn func() V, ttl time.Duration) func() V {
810
cache := NewCacheSized[uint64, V](1, int64(ttl.Seconds()))
911
return func() V {
@@ -13,6 +15,8 @@ func Memoize[V any](computeFn func() V, ttl time.Duration) func() V {
1315
}
1416
}
1517

18+
// Memoize1 returns a memoized version of the compute function with a single key and a specified TTL.
19+
// K is the type of the key, and V is the type of the value returned by the compute function.
1620
func Memoize1[K comparable, V any](computeFn func(K) V, ttl time.Duration) func(K) V {
1721
cache := NewCache[uint64, V](int64(ttl.Seconds()))
1822
return func(k K) V {
@@ -22,6 +26,8 @@ func Memoize1[K comparable, V any](computeFn func(K) V, ttl time.Duration) func(
2226
}
2327
}
2428

29+
// Memoize2 returns a memoized version of the compute function with two keys and a specified TTL.
30+
// K1 and K2 are the types of the keys, and V is the type of the value returned by the compute function.
2531
func Memoize2[K1, K2 comparable, V any](computeFn func(K1, K2) V, ttl time.Duration) func(K1, K2) V {
2632
cache := NewCache[uint64, V](int64(ttl.Seconds()))
2733
return func(key1 K1, key2 K2) V {
@@ -30,6 +36,9 @@ func Memoize2[K1, K2 comparable, V any](computeFn func(K1, K2) V, ttl time.Durat
3036
})
3137
}
3238
}
39+
40+
// Memoize3 returns a memoized version of the compute function with three keys and a specified TTL.
41+
// K1, K2, and K3 are the types of the keys, and V is the type of the value returned by the compute function.
3342
func Memoize3[K1, K2, K3 comparable, V any](computeFn func(K1, K2, K3) V, ttl time.Duration) func(K1, K2, K3) V {
3443
cache := NewCache[uint64, V](int64(ttl.Seconds()))
3544
return func(key1 K1, key2 K2, key3 K3) V {
@@ -39,6 +48,8 @@ func Memoize3[K1, K2, K3 comparable, V any](computeFn func(K1, K2, K3) V, ttl ti
3948
}
4049
}
4150

51+
// Memoize4 returns a memoized version of the compute function with four keys and a specified TTL.
52+
// K1, K2, K3, and K4 are the types of the keys, and V is the type of the value returned by the compute function.
4253
func Memoize4[K1, K2, K3, K4 comparable, V any](computeFn func(K1, K2, K3, K4) V, ttl time.Duration) func(K1, K2, K3, K4) V {
4354
cache := NewCache[uint64, V](int64(ttl.Seconds()))
4455
return func(key1 K1, key2 K2, key3 K3, key4 K4) V {
@@ -48,6 +59,8 @@ func Memoize4[K1, K2, K3, K4 comparable, V any](computeFn func(K1, K2, K3, K4) V
4859
}
4960
}
5061

62+
// Memoize5 returns a memoized version of the compute function with five keys and a specified TTL.
63+
// K1, K2, K3, K4, and K5 are the types of the keys, and V is the type of the value returned by the compute function.
5164
func Memoize5[K1, K2, K3, K4, K5 comparable, V any](computeFn func(K1, K2, K3, K4, K5) V, ttl time.Duration) func(K1, K2, K3, K4, K5) V {
5265
cache := NewCache[uint64, V](int64(ttl.Seconds()))
5366
return func(key1 K1, key2 K2, key3 K3, key4 K4, key5 K5) V {
@@ -57,6 +70,8 @@ func Memoize5[K1, K2, K3, K4, K5 comparable, V any](computeFn func(K1, K2, K3, K
5770
}
5871
}
5972

73+
// Memoize6 returns a memoized version of the compute function with six keys and a specified TTL.
74+
// K1, K2, K3, K4, K5, and K6 are the types of the keys, and V is the type of the value returned by the compute function.
6075
func Memoize6[K1, K2, K3, K4, K5, K6 comparable, V any](computeFn func(K1, K2, K3, K4, K5, K6) V, ttl time.Duration) func(K1, K2, K3, K4, K5, K6) V {
6176
cache := NewCache[uint64, V](int64(ttl.Seconds()))
6277
return func(key1 K1, key2 K2, key3 K3, key4 K4, key5 K5, key6 K6) V {
@@ -66,6 +81,8 @@ func Memoize6[K1, K2, K3, K4, K5, K6 comparable, V any](computeFn func(K1, K2, K
6681
}
6782
}
6883

84+
// Memoize7 returns a memoized version of the compute function with seven keys and a specified TTL.
85+
// K1, K2, K3, K4, K5, K6, and K7 are the types of the keys, and V is the type of the value returned by the compute function.
6986
func Memoize7[K1, K2, K3, K4, K5, K6, K7 comparable, V any](computeFn func(K1, K2, K3, K4, K5, K6, K7) V, ttl time.Duration) func(K1, K2, K3, K4, K5, K6, K7) V {
7087
cache := NewCache[uint64, V](int64(ttl.Seconds()))
7188
return func(key1 K1, key2 K2, key3 K3, key4 K4, key5 K5, key6 K6, key7 K7) V {

0 commit comments

Comments
 (0)