Skip to content

Commit 28e79db

Browse files
committed
implement a true atomic SetFn for atoms
1 parent 6bdbc63 commit 28e79db

5 files changed

Lines changed: 36 additions & 14 deletions

File tree

tsunami/app/atom.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ func (a Atom[T]) Get() T {
3939
compWaveId := vc.GetCompWaveId()
4040
vc.Root.AtomSetUsedBy(a.name, compWaveId, true)
4141
}
42-
val := a.client.GetAtomVal(a.name)
43-
return util.GetTypedAtomValue[T](val, a.name)
42+
val := a.client.Root.GetAtomVal(a.name)
43+
typedVal := util.GetTypedAtomValue[T](val, a.name)
44+
return typedVal
4445
}
4546

4647
// Set updates the atom's value
@@ -63,10 +64,11 @@ func (a Atom[T]) SetFn(fn func(T) T) {
6364
logInvalidAtomSet(a.name)
6465
return
6566
}
66-
val := a.client.GetAtomVal(a.name)
67-
typedVal := util.GetTypedAtomValue[T](val, a.name)
68-
newVal := fn(typedVal)
69-
if err := a.client.Root.SetAtomVal(a.name, newVal); err != nil {
67+
err := a.client.Root.SetFnAtomVal(a.name, func(val any) any {
68+
typedVal := util.GetTypedAtomValue[T](val, a.name)
69+
return fn(typedVal)
70+
})
71+
if err != nil {
7072
log.Printf("Failed to set atom value for %s: %v", a.name, err)
7173
return
7274
}

tsunami/demo/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test/

tsunami/engine/atomimpl.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,7 @@ func (a *AtomImpl[T]) GetVal() any {
2929
return a.val
3030
}
3131

32-
func (a *AtomImpl[T]) SetVal(val any) error {
33-
a.lock.Lock()
34-
defer a.lock.Unlock()
35-
32+
func (a *AtomImpl[T]) setVal_nolock(val any) error {
3633
if val == nil {
3734
var zero T
3835
a.val = zero
@@ -61,6 +58,20 @@ func (a *AtomImpl[T]) SetVal(val any) error {
6158
return nil
6259
}
6360

61+
func (a *AtomImpl[T]) SetVal(val any) error {
62+
a.lock.Lock()
63+
defer a.lock.Unlock()
64+
return a.setVal_nolock(val)
65+
}
66+
67+
func (a *AtomImpl[T]) SetFnVal(setFn func(any) any) error {
68+
a.lock.Lock()
69+
defer a.lock.Unlock()
70+
71+
newVal := setFn(a.val)
72+
return a.setVal_nolock(newVal)
73+
}
74+
6475
func (a *AtomImpl[T]) SetUsedBy(waveId string, used bool) {
6576
a.lock.Lock()
6677
defer a.lock.Unlock()

tsunami/engine/clientimpl.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,6 @@ func (c *ClientImpl) SendAsyncInitiation() error {
218218
}
219219
}
220220

221-
func (c *ClientImpl) GetAtomVal(name string) any {
222-
return c.Root.GetAtomVal(name)
223-
}
224-
225221
func makeNullRendered() *rpctypes.RenderedElem {
226222
return &rpctypes.RenderedElem{WaveId: uuid.New().String(), Tag: vdom.WaveNullTag}
227223
}

tsunami/engine/rootelem.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type EffectWorkElem struct {
2525
type genAtom interface {
2626
GetVal() any
2727
SetVal(any) error
28+
SetFnVal(func(any) any) error
2829
SetUsedBy(string, bool)
2930
GetUsedBy() []string
3031
}
@@ -157,6 +158,17 @@ func (r *RootElem) SetAtomVal(name string, val any) error {
157158
return atom.SetVal(val)
158159
}
159160

161+
func (r *RootElem) SetFnAtomVal(name string, setFn func(any) any) error {
162+
r.atomLock.Lock()
163+
defer r.atomLock.Unlock()
164+
165+
atom, ok := r.Atoms[name]
166+
if !ok {
167+
return fmt.Errorf("atom %q not found", name)
168+
}
169+
return atom.SetFnVal(setFn)
170+
}
171+
160172
func (r *RootElem) RemoveAtom(name string) {
161173
r.atomLock.Lock()
162174
defer r.atomLock.Unlock()

0 commit comments

Comments
 (0)