github.com/afumu/libc@v0.0.6/watch.go (about)

     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 "github.com/afumu/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  }