Skip to content

Instantly share code, notes, and snippets.

@fr33m0nk
Forked from ChristopherDavenport/Ref.go
Created March 31, 2024 14:26
Show Gist options
  • Save fr33m0nk/f64c035bdd592d23f6dcab47c7f8a079 to your computer and use it in GitHub Desktop.
Save fr33m0nk/f64c035bdd592d23f6dcab47c7f8a079 to your computer and use it in GitHub Desktop.
Basic Typed Concurrency
package concurrent
import (
"sync/atomic"
)
type Ref[A any] interface {
Get() A
Set(a A)
UpdateAndGet(f func (A) (A)) A
GetAndSet(a A) A
Underlying() atomic.Value
}
func NewRef[A any](a A) Ref[A] {
// switch v := a.(type) {
// case int64:
// default:
// _ = v
ref := internalRef[A]{}
ref.Set(a)
return ref
// }
}
type internalRef[A any] struct {
value atomic.Value
}
func (ref internalRef[A]) Underlying() atomic.Value {
return ref.value
}
func (ref internalRef[A]) Get() A {
returned := ref.value.Load()
return returned.(A)
}
func (ref internalRef[A]) Set(a A) {
ref.value.Store(a)
}
func (ref internalRef[A]) UpdateAndGet(f func (A) (A) ) A {
multiply := func (a A) (A, A) {
mod := f(a)
return mod, mod
}
return ModifyRef[A, A](ref, multiply)
}
func (ref internalRef[A]) GetAndSet(a A) A {
old := func (old A) (A, A) {
return a, old
}
return ModifyRef[A](ref, old)
}
func ModifyRef[A any, B any](ref Ref[A], f func(A) (A, B)) B {
updated := false
var out B
for !updated {
a := ref.Get()
u, b := f(a)
underlying := ref.Underlying()
updated = underlying.CompareAndSwap(a, u)
if (updated){
out = b
}
}
return out
}
func TryModifyRef[A any, B any](ref Ref[A], f func (A) (A, B)) *B {
var out *B
a := ref.Get()
u, b := f(a)
underlying := ref.Underlying()
updated := underlying.CompareAndSwap(a, u)
if (updated){
out = &b
}
return out
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment