Initial release
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
package wshub
|
||||
|
||||
import "sync"
|
||||
|
||||
// sigRing is a fixed-capacity circular buffer storing (time, value) pairs.
|
||||
// Writes come from the Hub.Run() goroutine; reads come from HTTP handler goroutines.
|
||||
// The embedded RWMutex protects concurrent access.
|
||||
type sigRing struct {
|
||||
mu sync.RWMutex
|
||||
t, v []float64
|
||||
cap int
|
||||
head, size int // next write position; current fill
|
||||
}
|
||||
|
||||
func newSigRing(capacity int) *sigRing {
|
||||
return &sigRing{
|
||||
t: make([]float64, capacity),
|
||||
v: make([]float64, capacity),
|
||||
cap: capacity,
|
||||
}
|
||||
}
|
||||
|
||||
// write appends (tArr[i], vArr[i]) pairs, overwriting oldest entries when full.
|
||||
func (rb *sigRing) write(tArr, vArr []float64) {
|
||||
rb.mu.Lock()
|
||||
defer rb.mu.Unlock()
|
||||
for i := 0; i < len(tArr); i++ {
|
||||
rb.t[rb.head] = tArr[i]
|
||||
rb.v[rb.head] = vArr[i]
|
||||
rb.head = (rb.head + 1) % rb.cap
|
||||
if rb.size < rb.cap {
|
||||
rb.size++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// slice returns copies of all (t, v) pairs whose timestamp falls in [t0, t1].
|
||||
// The returned slices are safe to use after the call without holding any lock.
|
||||
func (rb *sigRing) slice(t0, t1 float64) ([]float64, []float64) {
|
||||
rb.mu.RLock()
|
||||
defer rb.mu.RUnlock()
|
||||
|
||||
if rb.size == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
start := 0
|
||||
if rb.size == rb.cap {
|
||||
start = rb.head
|
||||
}
|
||||
physAt := func(k int) int { return (start + k) % rb.cap }
|
||||
|
||||
// Binary search for t0
|
||||
lo, hi := 0, rb.size
|
||||
for lo < hi {
|
||||
m := (lo + hi) >> 1
|
||||
if rb.t[physAt(m)] < t0 {
|
||||
lo = m + 1
|
||||
} else {
|
||||
hi = m
|
||||
}
|
||||
}
|
||||
kStart := lo
|
||||
|
||||
// Binary search for t1
|
||||
lo, hi = kStart, rb.size
|
||||
for lo < hi {
|
||||
m := (lo + hi) >> 1
|
||||
if rb.t[physAt(m)] <= t1 {
|
||||
lo = m + 1
|
||||
} else {
|
||||
hi = m
|
||||
}
|
||||
}
|
||||
kEnd := lo
|
||||
|
||||
n := kEnd - kStart
|
||||
if n <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
outT := make([]float64, n)
|
||||
outV := make([]float64, n)
|
||||
for i := 0; i < n; i++ {
|
||||
p := physAt(kStart + i)
|
||||
outT[i] = rb.t[p]
|
||||
outV[i] = rb.v[p]
|
||||
}
|
||||
return outT, outV
|
||||
}
|
||||
Reference in New Issue
Block a user