Skip to content

Commit 20a68e9

Browse files
committed
createatom flow
1 parent 40969b2 commit 20a68e9

5 files changed

Lines changed: 61 additions & 32 deletions

File tree

tsunami/app/defaultclient.go

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,21 @@ func SendAsyncInitiation() error {
3939
func ConfigAtom[T any](name string, defaultValue T) Atom[T] {
4040
fullName := "$config." + name
4141
client := engine.GetDefaultClient()
42-
// Set the default value if not already set
43-
if client.GetAtomVal(fullName) == nil {
44-
client.SetAtomVal(fullName, defaultValue)
45-
}
42+
client.CreateAtom(fullName, defaultValue)
4643
return Atom[T]{name: fullName, client: client}
4744
}
4845

4946
func DataAtom[T any](name string, defaultValue T) Atom[T] {
5047
fullName := "$data." + name
5148
client := engine.GetDefaultClient()
52-
// Set the default value if not already set
53-
if client.GetAtomVal(fullName) == nil {
54-
client.SetAtomVal(fullName, defaultValue)
55-
}
49+
client.CreateAtom(fullName, defaultValue)
5650
return Atom[T]{name: fullName, client: client}
5751
}
5852

5953
func SharedAtom[T any](name string, defaultValue T) Atom[T] {
6054
fullName := "$shared." + name
6155
client := engine.GetDefaultClient()
62-
// Set the default value if not already set
63-
if client.GetAtomVal(fullName) == nil {
64-
client.SetAtomVal(fullName, defaultValue)
65-
}
56+
client.CreateAtom(fullName, defaultValue)
6657
return Atom[T]{name: fullName, client: client}
6758
}
6859

tsunami/engine/atomimpl.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2025, Command Line Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package engine
5+
6+
import "sync"
7+
8+
type atomImpl struct {
9+
lock *sync.Mutex
10+
val any
11+
UsedBy map[string]bool // component waveid -> true
12+
}
13+
14+
func makeAtom(initialVal any) *atomImpl {
15+
return &atomImpl{
16+
lock: &sync.Mutex{},
17+
val: initialVal,
18+
UsedBy: make(map[string]bool),
19+
}
20+
}
21+
22+
func (a *atomImpl) GetVal() any {
23+
a.lock.Lock()
24+
defer a.lock.Unlock()
25+
return a.val
26+
}
27+
28+
func (a *atomImpl) SetVal(val any) {
29+
a.lock.Lock()
30+
defer a.lock.Unlock()
31+
a.val = val
32+
}

tsunami/engine/clientimpl.go

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

221+
func (c *ClientImpl) CreateAtom(name string, initialVal any) {
222+
c.Root.CreateAtom(name, initialVal)
223+
}
224+
221225
func (c *ClientImpl) SetAtomVal(name string, val any) {
222226
c.Root.SetAtomVal(name, val, true)
223227
}

tsunami/engine/hooks.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func UseLocal(vc *VDomContextImpl, initialVal any) string {
116116
atomName := "$local." + vc.GetCompWaveId() + "#" + strconv.Itoa(hookVal.Idx)
117117
if !hookVal.Init {
118118
hookVal.Init = true
119-
vc.Root.SetAtomVal(atomName, initialVal, false)
119+
vc.Root.CreateAtom(atomName, initialVal)
120120
closedAtomName := atomName
121121
hookVal.UnmountFn = func() {
122122
vc.Root.RemoveAtom(closedAtomName)

tsunami/engine/rootelem.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,6 @@ type RenderOpts struct {
3636
Resync bool
3737
}
3838

39-
type atomImpl struct {
40-
Val any
41-
UsedBy map[string]bool // component waveid -> true
42-
}
43-
4439
type EffectWorkElem struct {
4540
Id string
4641
EffectIndex int
@@ -79,7 +74,7 @@ func (r *RootElem) GetDataMap() map[string]any {
7974
for atomName, atom := range r.Atoms {
8075
if strings.HasPrefix(atomName, "$data.") {
8176
strippedName := strings.TrimPrefix(atomName, "$data.")
82-
result[strippedName] = atom.Val
77+
result[strippedName] = atom.GetVal()
8378
}
8479
}
8580
return result
@@ -93,7 +88,7 @@ func (r *RootElem) GetConfigMap() map[string]any {
9388
for atomName, atom := range r.Atoms {
9489
if strings.HasPrefix(atomName, "$config.") {
9590
strippedName := strings.TrimPrefix(atomName, "$config.")
96-
result[strippedName] = atom.Val
91+
result[strippedName] = atom.GetVal()
9792
}
9893
}
9994
return result
@@ -108,13 +103,14 @@ func MakeRoot() *RootElem {
108103
}
109104
}
110105

111-
func (r *RootElem) ensureAtomNoLock(name string) *atomImpl {
112-
atom, ok := r.Atoms[name]
113-
if !ok {
114-
atom = &atomImpl{UsedBy: make(map[string]bool)}
115-
r.Atoms[name] = atom
106+
func (r *RootElem) CreateAtom(name string, initialVal any) {
107+
r.atomLock.Lock()
108+
defer r.atomLock.Unlock()
109+
110+
if _, ok := r.Atoms[name]; ok {
111+
panic(fmt.Sprintf("atom %s already exists", name))
116112
}
117-
return atom
113+
r.Atoms[name] = makeAtom(initialVal)
118114
}
119115

120116
// we can do better here with an inverted map, but
@@ -132,7 +128,10 @@ func (r *RootElem) AtomSetUsedBy(atomName string, waveId string, used bool) {
132128
r.atomLock.Lock()
133129
defer r.atomLock.Unlock()
134130

135-
atom := r.ensureAtomNoLock(atomName)
131+
atom, ok := r.Atoms[atomName]
132+
if !ok {
133+
return
134+
}
136135
if used {
137136
atom.UsedBy[waveId] = true
138137
} else {
@@ -161,23 +160,26 @@ func (r *RootElem) GetAtomVal(name string) any {
161160
if !ok {
162161
return nil
163162
}
164-
return atom.Val
163+
return atom.GetVal()
165164
}
166165

167166
func (r *RootElem) SetAtomVal(name string, val any, markDirty bool) {
168167
r.atomLock.Lock()
169168
defer r.atomLock.Unlock()
170169

171-
atom := r.ensureAtomNoLock(name)
170+
atom, ok := r.Atoms[name]
171+
if !ok {
172+
return
173+
}
172174
if !markDirty {
173-
atom.Val = val
175+
atom.SetVal(val)
174176
return
175177
}
176178
// try to avoid setting the value and marking as dirty if it's the "same"
177-
if util.JsonValEqual(val, atom.Val) {
179+
if util.JsonValEqual(val, atom.GetVal()) {
178180
return
179181
}
180-
atom.Val = val
182+
atom.SetVal(val)
181183
}
182184

183185
func (r *RootElem) RemoveAtom(name string) {

0 commit comments

Comments
 (0)