Skip to content

Commit 861552a

Browse files
committed
Implement watches for atom
Signed-off-by: James Hamlin <jfhamlin@gmail.com>
1 parent aedda07 commit 861552a

13 files changed

Lines changed: 71 additions & 22 deletions

pkg/gen/gljimports/gljimports_darwin_amd64.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,6 +3562,7 @@ func RegisterImports(_register func(string, interface{})) {
35623562
_register("github.com/glojurelang/glojure/pkg/lang.IDeref", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDeref)(nil)).Elem())
35633563
_register("github.com/glojurelang/glojure/pkg/lang.IDrop", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDrop)(nil)).Elem())
35643564
_register("github.com/glojurelang/glojure/pkg/lang.IEditableCollection", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IEditableCollection)(nil)).Elem())
3565+
_register("github.com/glojurelang/glojure/pkg/lang.IExceptionInfo", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IExceptionInfo)(nil)).Elem())
35653566
_register("github.com/glojurelang/glojure/pkg/lang.IFn", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IFn)(nil)).Elem())
35663567
_register("github.com/glojurelang/glojure/pkg/lang.IHashEq", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IHashEq)(nil)).Elem())
35673568
_register("github.com/glojurelang/glojure/pkg/lang.IKVReduce", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IKVReduce)(nil)).Elem())

pkg/gen/gljimports/gljimports_darwin_arm64.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,6 +3562,7 @@ func RegisterImports(_register func(string, interface{})) {
35623562
_register("github.com/glojurelang/glojure/pkg/lang.IDeref", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDeref)(nil)).Elem())
35633563
_register("github.com/glojurelang/glojure/pkg/lang.IDrop", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDrop)(nil)).Elem())
35643564
_register("github.com/glojurelang/glojure/pkg/lang.IEditableCollection", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IEditableCollection)(nil)).Elem())
3565+
_register("github.com/glojurelang/glojure/pkg/lang.IExceptionInfo", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IExceptionInfo)(nil)).Elem())
35653566
_register("github.com/glojurelang/glojure/pkg/lang.IFn", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IFn)(nil)).Elem())
35663567
_register("github.com/glojurelang/glojure/pkg/lang.IHashEq", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IHashEq)(nil)).Elem())
35673568
_register("github.com/glojurelang/glojure/pkg/lang.IKVReduce", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IKVReduce)(nil)).Elem())

pkg/gen/gljimports/gljimports_js_wasm.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,6 +3562,7 @@ func RegisterImports(_register func(string, interface{})) {
35623562
_register("github.com/glojurelang/glojure/pkg/lang.IDeref", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDeref)(nil)).Elem())
35633563
_register("github.com/glojurelang/glojure/pkg/lang.IDrop", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDrop)(nil)).Elem())
35643564
_register("github.com/glojurelang/glojure/pkg/lang.IEditableCollection", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IEditableCollection)(nil)).Elem())
3565+
_register("github.com/glojurelang/glojure/pkg/lang.IExceptionInfo", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IExceptionInfo)(nil)).Elem())
35653566
_register("github.com/glojurelang/glojure/pkg/lang.IFn", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IFn)(nil)).Elem())
35663567
_register("github.com/glojurelang/glojure/pkg/lang.IHashEq", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IHashEq)(nil)).Elem())
35673568
_register("github.com/glojurelang/glojure/pkg/lang.IKVReduce", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IKVReduce)(nil)).Elem())

pkg/gen/gljimports/gljimports_linux_amd64.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,6 +3562,7 @@ func RegisterImports(_register func(string, interface{})) {
35623562
_register("github.com/glojurelang/glojure/pkg/lang.IDeref", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDeref)(nil)).Elem())
35633563
_register("github.com/glojurelang/glojure/pkg/lang.IDrop", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDrop)(nil)).Elem())
35643564
_register("github.com/glojurelang/glojure/pkg/lang.IEditableCollection", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IEditableCollection)(nil)).Elem())
3565+
_register("github.com/glojurelang/glojure/pkg/lang.IExceptionInfo", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IExceptionInfo)(nil)).Elem())
35653566
_register("github.com/glojurelang/glojure/pkg/lang.IFn", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IFn)(nil)).Elem())
35663567
_register("github.com/glojurelang/glojure/pkg/lang.IHashEq", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IHashEq)(nil)).Elem())
35673568
_register("github.com/glojurelang/glojure/pkg/lang.IKVReduce", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IKVReduce)(nil)).Elem())

pkg/gen/gljimports/gljimports_linux_arm64.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,6 +3562,7 @@ func RegisterImports(_register func(string, interface{})) {
35623562
_register("github.com/glojurelang/glojure/pkg/lang.IDeref", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDeref)(nil)).Elem())
35633563
_register("github.com/glojurelang/glojure/pkg/lang.IDrop", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDrop)(nil)).Elem())
35643564
_register("github.com/glojurelang/glojure/pkg/lang.IEditableCollection", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IEditableCollection)(nil)).Elem())
3565+
_register("github.com/glojurelang/glojure/pkg/lang.IExceptionInfo", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IExceptionInfo)(nil)).Elem())
35653566
_register("github.com/glojurelang/glojure/pkg/lang.IFn", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IFn)(nil)).Elem())
35663567
_register("github.com/glojurelang/glojure/pkg/lang.IHashEq", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IHashEq)(nil)).Elem())
35673568
_register("github.com/glojurelang/glojure/pkg/lang.IKVReduce", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IKVReduce)(nil)).Elem())

pkg/gen/gljimports/gljimports_windows_amd64.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,6 +3562,7 @@ func RegisterImports(_register func(string, interface{})) {
35623562
_register("github.com/glojurelang/glojure/pkg/lang.IDeref", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDeref)(nil)).Elem())
35633563
_register("github.com/glojurelang/glojure/pkg/lang.IDrop", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDrop)(nil)).Elem())
35643564
_register("github.com/glojurelang/glojure/pkg/lang.IEditableCollection", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IEditableCollection)(nil)).Elem())
3565+
_register("github.com/glojurelang/glojure/pkg/lang.IExceptionInfo", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IExceptionInfo)(nil)).Elem())
35653566
_register("github.com/glojurelang/glojure/pkg/lang.IFn", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IFn)(nil)).Elem())
35663567
_register("github.com/glojurelang/glojure/pkg/lang.IHashEq", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IHashEq)(nil)).Elem())
35673568
_register("github.com/glojurelang/glojure/pkg/lang.IKVReduce", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IKVReduce)(nil)).Elem())

pkg/gen/gljimports/gljimports_windows_arm.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,6 +3562,7 @@ func RegisterImports(_register func(string, interface{})) {
35623562
_register("github.com/glojurelang/glojure/pkg/lang.IDeref", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDeref)(nil)).Elem())
35633563
_register("github.com/glojurelang/glojure/pkg/lang.IDrop", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDrop)(nil)).Elem())
35643564
_register("github.com/glojurelang/glojure/pkg/lang.IEditableCollection", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IEditableCollection)(nil)).Elem())
3565+
_register("github.com/glojurelang/glojure/pkg/lang.IExceptionInfo", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IExceptionInfo)(nil)).Elem())
35653566
_register("github.com/glojurelang/glojure/pkg/lang.IFn", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IFn)(nil)).Elem())
35663567
_register("github.com/glojurelang/glojure/pkg/lang.IHashEq", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IHashEq)(nil)).Elem())
35673568
_register("github.com/glojurelang/glojure/pkg/lang.IKVReduce", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IKVReduce)(nil)).Elem())

pkg/lang/atom.go

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import "sync/atomic"
44

55
type (
66
Atom struct {
7-
state atomic.Value
7+
state atomic.Value
8+
watches IPersistentMap
89

910
meta IPersistentMap
1011
}
@@ -18,6 +19,7 @@ var (
1819
func NewAtom(val any) *Atom {
1920
a := &Atom{}
2021
a.state.Store(Box{val})
22+
a.watches = emptyMap
2123
return a
2224
}
2325

@@ -33,11 +35,35 @@ func (a *Atom) Deref() interface{} {
3335
return a.state.Load().(Box).val
3436
}
3537

36-
func (a *Atom) SetValidator(vf IFn) { panic("not implemented") }
37-
func (a *Atom) Validator() IFn { panic("not implemented") }
38-
func (a *Atom) Watches() IPersistentMap { panic("not implemented") }
39-
func (a *Atom) AddWatch(key interface{}, fn IFn) { panic("not implemented") }
40-
func (a *Atom) RemoveWatch(key interface{}) { panic("not implemented") }
38+
func (a *Atom) SetValidator(vf IFn) { panic("not implemented") }
39+
func (a *Atom) Validator() IFn { panic("not implemented") }
40+
func (a *Atom) Watches() IPersistentMap {
41+
return a.watches
42+
}
43+
44+
func (a *Atom) AddWatch(key interface{}, fn IFn) IRef {
45+
a.watches = a.watches.Assoc(key, fn).(IPersistentMap)
46+
return a
47+
}
48+
49+
func (a *Atom) RemoveWatch(key interface{}) {
50+
a.watches = a.watches.Without(key)
51+
}
52+
53+
func (a *Atom) notifyWatches(oldVal, newVal interface{}) {
54+
watches := a.watches
55+
if watches == nil || watches.Count() == 0 {
56+
return
57+
}
58+
59+
for seq := watches.Seq(); seq != nil; seq = seq.Next() {
60+
entry := seq.First().(IMapEntry)
61+
key := entry.Key()
62+
fn := entry.Val().(IFn)
63+
// Call watch function with key, ref, old-state, new-state
64+
fn.Invoke(key, a, oldVal, newVal)
65+
}
66+
}
4167

4268
func (a *Atom) Swap(f IFn, args ISeq) interface{} {
4369
for {
@@ -51,16 +77,19 @@ func (a *Atom) Swap(f IFn, args ISeq) interface{} {
5177

5278
func (a *Atom) CompareAndSet(oldv, newv interface{}) bool {
5379
// TODO: validate
54-
// TODO: notifyWatches
55-
return a.state.CompareAndSwap(Box{val: oldv}, Box{val: newv})
80+
swapped := a.state.CompareAndSwap(Box{val: oldv}, Box{val: newv})
81+
if swapped {
82+
a.notifyWatches(oldv, newv)
83+
}
84+
return swapped
5685
}
5786

5887
func (a *Atom) Reset(newVal interface{}) interface{} {
59-
// old := a.state.Load().(Box)
88+
old := a.state.Load().(Box)
6089
// TODO: validate
6190

6291
a.state.Store(Box{newVal})
63-
// TODO: notifyWatches
92+
a.notifyWatches(old.val, newVal)
6493
return newVal
6594
}
6695

pkg/lang/interfaces.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ type (
285285
SetValidator(vf IFn)
286286
Validator() IFn
287287
Watches() IPersistentMap
288-
AddWatch(key any, fn IFn)
288+
AddWatch(key any, fn IFn) IRef
289289
RemoveWatch(key any)
290290
}
291291

@@ -320,6 +320,16 @@ type (
320320
Next() any
321321
}
322322

323+
////////////////////////////////////////////////////////////////////////////
324+
325+
// IExceptionInfo is an interface for exceptions that carry data (a
326+
// map) as additional payload. Clojure programs that need richer
327+
// semantics for exceptions should use this in lieu of defining
328+
// project-specific error types..
329+
IExceptionInfo interface {
330+
GetData() IPersistentMap
331+
}
332+
323333
////////////////////////////////////////////////////////////////////////////
324334
// Abstract classes
325335
//

pkg/lang/var.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ func (v *Var) Watches() IPersistentMap {
249249
panic("not implemented")
250250
}
251251

252-
func (v *Var) AddWatch(key interface{}, fn IFn) {
252+
func (v *Var) AddWatch(key interface{}, fn IFn) IRef {
253253
panic("not implemented")
254254
}
255255

0 commit comments

Comments
 (0)