60 lines
1.2 KiB
Go
60 lines
1.2 KiB
Go
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package portlist
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
type Poller struct {
|
|
C chan List // new data when it arrives; closed when done
|
|
quitCh chan struct{} // close this to force exit
|
|
Err error // last returned error code, if any
|
|
prev List // most recent data
|
|
}
|
|
|
|
func NewPoller() (*Poller, error) {
|
|
p := &Poller{
|
|
C: make(chan List),
|
|
quitCh: make(chan struct{}),
|
|
}
|
|
// Do one initial poll synchronously, so the caller can react
|
|
// to any obvious errors.
|
|
p.prev, p.Err = GetList(nil)
|
|
return p, p.Err
|
|
}
|
|
|
|
func (p *Poller) Close() {
|
|
close(p.quitCh)
|
|
<-p.C
|
|
}
|
|
|
|
// Poll periodically. Run this in a goroutine if you want.
|
|
func (p *Poller) Run() error {
|
|
defer close(p.C)
|
|
tick := time.NewTicker(POLL_SECONDS * time.Second)
|
|
defer tick.Stop()
|
|
|
|
// Send out the pre-generated initial value
|
|
p.C <- p.prev
|
|
|
|
for {
|
|
select {
|
|
case <-tick.C:
|
|
pl, err := GetList(p.prev)
|
|
if err != nil {
|
|
p.Err = err
|
|
return p.Err
|
|
}
|
|
if !pl.SameInodes(p.prev) {
|
|
p.prev = pl
|
|
p.C <- pl
|
|
}
|
|
case <-p.quitCh:
|
|
return nil
|
|
}
|
|
}
|
|
}
|