watch.go (5557B)
1 // Copyright 2021 The Libc Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package libc // import "modernc.org/libc" 6 7 import ( 8 "fmt" 9 "math" 10 "os" 11 "sync" 12 "unsafe" 13 ) 14 15 var ( 16 watches = map[uintptr]watch{} 17 watchesMu sync.Mutex 18 ) 19 20 type watch interface { 21 msg() string 22 } 23 24 type watcher string 25 26 func (w watcher) msg() string { 27 if w == "" { 28 return "" 29 } 30 31 return fmt.Sprintf(": %s", w) 32 } 33 34 type watchInt8 struct { 35 val int8 36 watcher 37 } 38 39 func WatchInt8(p uintptr, msg string) { 40 watchesMu.Lock() 41 watches[p] = &watchInt8{*(*int8)(unsafe.Pointer(p)), watcher(msg)} 42 watchesMu.Unlock() 43 } 44 45 type watchUint8 struct { 46 val uint8 47 watcher 48 } 49 50 func WatchUint8(p uintptr, msg string) { 51 watchesMu.Lock() 52 watches[p] = &watchUint8{*(*uint8)(unsafe.Pointer(p)), watcher(msg)} 53 watchesMu.Unlock() 54 } 55 56 type watchInt16 struct { 57 val int16 58 watcher 59 } 60 61 func WatchInt16(p uintptr, msg string) { 62 watchesMu.Lock() 63 watches[p] = &watchInt16{*(*int16)(unsafe.Pointer(p)), watcher(msg)} 64 watchesMu.Unlock() 65 } 66 67 type watchUint16 struct { 68 val uint16 69 watcher 70 } 71 72 func WatchUint16(p uintptr, msg string) { 73 watchesMu.Lock() 74 watches[p] = &watchUint16{*(*uint16)(unsafe.Pointer(p)), watcher(msg)} 75 watchesMu.Unlock() 76 } 77 78 type watchInt32 struct { 79 val int32 80 watcher 81 } 82 83 func WatchInt32(p uintptr, msg string) { 84 watchesMu.Lock() 85 watches[p] = &watchInt32{*(*int32)(unsafe.Pointer(p)), watcher(msg)} 86 watchesMu.Unlock() 87 } 88 89 type watchUint32 struct { 90 val uint32 91 watcher 92 } 93 94 func WatchUint32(p uintptr, msg string) { 95 watchesMu.Lock() 96 watches[p] = &watchUint32{*(*uint32)(unsafe.Pointer(p)), watcher(msg)} 97 watchesMu.Unlock() 98 } 99 100 type watchInt64 struct { 101 val int64 102 watcher 103 } 104 105 func WatchInt64(p uintptr, msg string) { 106 watchesMu.Lock() 107 watches[p] = &watchInt64{*(*int64)(unsafe.Pointer(p)), watcher(msg)} 108 watchesMu.Unlock() 109 } 110 111 type watchUint64 struct { 112 val uint64 113 watcher 114 } 115 116 func WatchUint64(p uintptr, msg string) { 117 watchesMu.Lock() 118 watches[p] = &watchUint64{*(*uint64)(unsafe.Pointer(p)), watcher(msg)} 119 watchesMu.Unlock() 120 } 121 122 type watchFloat32 struct { 123 val float32 124 watcher 125 } 126 127 func WatchFloat32(p uintptr, msg string) { 128 watchesMu.Lock() 129 watches[p] = &watchFloat32{*(*float32)(unsafe.Pointer(p)), watcher(msg)} 130 watchesMu.Unlock() 131 } 132 133 type watchFloat64 struct { 134 val float64 135 watcher 136 } 137 138 func WatchFloat64(p uintptr, msg string) { 139 watchesMu.Lock() 140 watches[p] = &watchFloat64{*(*float64)(unsafe.Pointer(p)), watcher(msg)} 141 watchesMu.Unlock() 142 } 143 144 type watchPtr struct { 145 val uintptr 146 watcher 147 } 148 149 func WatchPtr(p uintptr, msg string) { 150 watchesMu.Lock() 151 watches[p] = &watchPtr{*(*uintptr)(unsafe.Pointer(p)), watcher(msg)} 152 watchesMu.Unlock() 153 } 154 155 func Watch() { 156 watchesMu.Lock() 157 flush := false 158 for p, v := range watches { 159 switch x := v.(type) { 160 case *watchInt8: 161 if val := *(*int8)(unsafe.Pointer(p)); val != x.val { 162 flush = true 163 fmt.Fprintf(os.Stderr, "%v: int8@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg()) 164 x.val = val 165 } 166 case *watchUint8: 167 if val := *(*uint8)(unsafe.Pointer(p)); val != x.val { 168 flush = true 169 fmt.Fprintf(os.Stderr, "%v: uint8@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg()) 170 x.val = val 171 } 172 case *watchInt16: 173 if val := *(*int16)(unsafe.Pointer(p)); val != x.val { 174 flush = true 175 fmt.Fprintf(os.Stderr, "%v: int16@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg()) 176 x.val = val 177 } 178 case *watchUint16: 179 if val := *(*uint16)(unsafe.Pointer(p)); val != x.val { 180 flush = true 181 fmt.Fprintf(os.Stderr, "%v: uint16@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg()) 182 x.val = val 183 } 184 case *watchInt32: 185 if val := *(*int32)(unsafe.Pointer(p)); val != x.val { 186 flush = true 187 fmt.Fprintf(os.Stderr, "%v: int32@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg()) 188 x.val = val 189 } 190 case *watchUint32: 191 if val := *(*uint32)(unsafe.Pointer(p)); val != x.val { 192 flush = true 193 fmt.Fprintf(os.Stderr, "%v: uint32@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg()) 194 x.val = val 195 } 196 case *watchInt64: 197 if val := *(*int64)(unsafe.Pointer(p)); val != x.val { 198 flush = true 199 fmt.Fprintf(os.Stderr, "%v: int64@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg()) 200 x.val = val 201 } 202 case *watchUint64: 203 if val := *(*uint64)(unsafe.Pointer(p)); val != x.val { 204 flush = true 205 fmt.Fprintf(os.Stderr, "%v: uint64@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg()) 206 x.val = val 207 } 208 case *watchFloat32: 209 if val := *(*float32)(unsafe.Pointer(p)); math.Float32bits(val) != math.Float32bits(x.val) { 210 flush = true 211 fmt.Fprintf(os.Stderr, "%v: float32@%#x was %v(%#x), new %v(%#x)%s\n", origin(2), p, x.val, math.Float32bits(x.val), val, math.Float32bits(val), x.msg()) 212 x.val = val 213 } 214 case *watchFloat64: 215 if val := *(*float64)(unsafe.Pointer(p)); math.Float64bits(val) != math.Float64bits(x.val) { 216 flush = true 217 fmt.Fprintf(os.Stderr, "%v: float64@%#x was %v(%#x), new %v(%#x)%s\n", origin(2), p, x.val, math.Float64bits(x.val), val, math.Float64bits(val), x.msg()) 218 x.val = val 219 } 220 case *watchPtr: 221 if val := *(*uintptr)(unsafe.Pointer(p)); val != x.val { 222 flush = true 223 fmt.Fprintf(os.Stderr, "%v: ptr@%#x was %#x, new %#x%s\n", origin(2), p, x.val, val, x.msg()) 224 x.val = val 225 } 226 default: 227 panic(todo("%T", x)) 228 } 229 } 230 if flush { 231 os.Stderr.Sync() 232 } 233 watchesMu.Unlock() 234 } 235 236 func WatchDelete(p uintptr) { 237 watchesMu.Lock() 238 delete(watches, p) 239 watchesMu.Unlock() 240 }