package sensor import "sync" // Hub broadcasts refresh notifications. Its zero value is ready to use, and all // methods are concurrency-safe. Bursts coalesce so slow subscribers never block // the sender or other subscribers. type Hub struct { mu sync.Mutex subscribers map[chan struct{}]struct{} } // Subscribe registers a buffered notification channel. The caller must cancel // when finished; cancellation is idempotent and leaves the channel open. func (h *Hub) Subscribe() (<-chan struct{}, func()) { events := make(chan struct{}, 1) h.mu.Lock() if h.subscribers == nil { h.subscribers = make(map[chan struct{}]struct{}) } h.subscribers[events] = struct{}{} h.mu.Unlock() return events, func() { h.mu.Lock() delete(h.subscribers, events) h.mu.Unlock() } } // Notify queues at most one pending notification per subscriber without waiting // for readers. Notifications carry no data; clients fetch the current snapshot. func (h *Hub) Notify() { h.mu.Lock() defer h.mu.Unlock() for events := range h.subscribers { select { case events <- struct{}{}: default: } } }