summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-kv/v2/format/cache.go
diff options
context:
space:
mode:
authorLibravatar kim <grufwub@gmail.com>2025-08-10 15:05:54 +0200
committerLibravatar kim <gruf@noreply.codeberg.org>2025-08-10 15:05:54 +0200
commit67100809b399b60e58490fa8b1c0a72be75ac820 (patch)
treeae6df939bf9fe557a766120bee3363f89b47f961 /vendor/codeberg.org/gruf/go-kv/v2/format/cache.go
parent[feature + performance] add JSON logging format (#4355) (diff)
downloadgotosocial-67100809b399b60e58490fa8b1c0a72be75ac820.tar.xz
[chore] update dependencies (#4361)
- codeberg.org/gruf/go-kv/v2 v2.0.5 => v2.0.6 - github.com/coreos/go-oidc/v3 v3.14.1 => v3.15.0 - github.com/miekg/dns v1.1.67 => v1.1.68 - github.com/tdewolff/minify/v2 v2.23.9 => v2.23.11 - github.com/yuin/goldmark v1.7.12 => v1.7.13 - golang.org/x/crypto v0.40.0 => v0.41.0 - golang.org/x/image v0.29.0 => v0.30.0 - golang.org/x/net v0.42.0 => v0.43.0 - golang.org/x/sys v0.34.0 => v0.35.0 - golang.org/x/text v0.27.0 => v0.28.0 - modernc.org/sqlite v1.38.0 => v1.38.2 Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4361 Co-authored-by: kim <grufwub@gmail.com> Co-committed-by: kim <grufwub@gmail.com>
Diffstat (limited to 'vendor/codeberg.org/gruf/go-kv/v2/format/cache.go')
-rw-r--r--vendor/codeberg.org/gruf/go-kv/v2/format/cache.go60
1 files changed, 60 insertions, 0 deletions
diff --git a/vendor/codeberg.org/gruf/go-kv/v2/format/cache.go b/vendor/codeberg.org/gruf/go-kv/v2/format/cache.go
new file mode 100644
index 000000000..8c9bfa210
--- /dev/null
+++ b/vendor/codeberg.org/gruf/go-kv/v2/format/cache.go
@@ -0,0 +1,60 @@
+package format
+
+import (
+ "sync/atomic"
+ "unsafe"
+
+ "codeberg.org/gruf/go-xunsafe"
+)
+
+// cache is a concurrency-safe map[xunsafe.TypeInfo]FormatFunc
+// cache, designed for heavy reads but with unfortunately expensive
+// writes. it is designed such that after some initial load period
+// in which functions are cached by types, all future ops are reads.
+type cache struct{ p unsafe.Pointer }
+
+// Get will check cache for format func under key.
+func (c *cache) Get(t xunsafe.TypeInfo) FormatFunc {
+ if p := c.load(); p != nil {
+ return (*p)[t]
+ }
+ return nil
+}
+
+// Put will place given format func in cache under key, if not already exists.
+func (c *cache) Put(t xunsafe.TypeInfo, fn FormatFunc) {
+ for {
+ p := c.load()
+
+ var cache map[xunsafe.TypeInfo]FormatFunc
+
+ if p != nil {
+ if _, ok := (*p)[t]; ok {
+ return
+ }
+
+ cache = make(map[xunsafe.TypeInfo]FormatFunc, len(*p)+1)
+ for key, value := range *p {
+ cache[key] = value
+ }
+ } else {
+ cache = make(map[xunsafe.TypeInfo]FormatFunc, 1)
+ }
+
+ cache[t] = fn
+
+ if c.cas(p, &cache) {
+ return
+ }
+ }
+}
+
+// load is a typed wrapper around atomic.LoadPointer().
+func (c *cache) load() *map[xunsafe.TypeInfo]FormatFunc {
+ return (*map[xunsafe.TypeInfo]FormatFunc)(atomic.LoadPointer(&c.p))
+}
+
+// cas is a typed wrapper around atomic.CompareAndSwapPointer().
+func (c *cache) cas(old, new *map[xunsafe.TypeInfo]FormatFunc) bool {
+ return atomic.CompareAndSwapPointer(&c.p, unsafe.Pointer(old), unsafe.Pointer(new))
+}