diff --git a/exp/sensor/android.go b/exp/sensor/android.go index 7e9ae4d..8b36ded 100644 --- a/exp/sensor/android.go +++ b/exp/sensor/android.go @@ -101,8 +101,10 @@ func init() { }() } -func enable(s Sender, t Type, delay time.Duration) error { - startCollecting(s) +// enable enables the sensor t on sender. A non-nil sender is +// required before calling enable. +func enable(t Type, delay time.Duration) error { + startCollecting() var err error done := make(chan struct{}) @@ -114,7 +116,7 @@ func enable(s Sender, t Type, delay time.Duration) error { return err } -func startCollecting(s Sender) { +func startCollecting() { collectingMu.Lock() defer collectingMu.Unlock() @@ -135,7 +137,7 @@ func startCollecting(s Sender) { } <-done for i := 0; i < n; i++ { - s.Send(ev[i]) + sender.Send(ev[i]) } } }() diff --git a/exp/sensor/darwin_armx.go b/exp/sensor/darwin_armx.go index c6a54b2..52cfed7 100644 --- a/exp/sensor/darwin_armx.go +++ b/exp/sensor/darwin_armx.go @@ -60,7 +60,9 @@ func init() { const minDelay = 10 * time.Millisecond -func enable(s Sender, t Type, delay time.Duration) error { +// enable enables the sensor t on sender. A non-nil sender is +// required before calling enable. +func enable(t Type, delay time.Duration) error { channels.Lock() defer channels.Unlock() @@ -82,7 +84,7 @@ func enable(s Sender, t Type, delay time.Duration) error { case Magnetometer: C.GoIOS_startMagneto(interval) } - go pollSensor(s, t, delay, channels.done[t]) + go pollSensor(t, delay, channels.done[t]) return nil } @@ -107,7 +109,7 @@ func disable(t Type) error { return nil } -func pollSensor(s Sender, t Type, d time.Duration, done chan struct{}) { +func pollSensor(t Type, d time.Duration, done chan struct{}) { var lastTimestamp int64 var timestamp C.int64_t @@ -133,7 +135,7 @@ func pollSensor(s Sender, t Type, d time.Duration, done chan struct{}) { if ts > lastTimestamp { // TODO(jbd): Do we need to convert the values to another unit? // How does iOS units compare to the Android units. - s.Send(Event{ + sender.Send(Event{ Sensor: t, Timestamp: ts, Data: []float64{float64(ev[0]), float64(ev[1]), float64(ev[2])}, diff --git a/exp/sensor/notmobile.go b/exp/sensor/notmobile.go index ee1636a..1f8b0f0 100644 --- a/exp/sensor/notmobile.go +++ b/exp/sensor/notmobile.go @@ -11,7 +11,7 @@ import ( "time" ) -func enable(s Sender, t Type, delay time.Duration) error { +func enable(t Type, delay time.Duration) error { return errors.New("sensor: no sensors available") } diff --git a/exp/sensor/sensor.go b/exp/sensor/sensor.go index 74d1ae1..2c697b6 100644 --- a/exp/sensor/sensor.go +++ b/exp/sensor/sensor.go @@ -7,6 +7,7 @@ package sensor // import "golang.org/x/mobile/exp/sensor" import ( "errors" + "sync" "time" ) @@ -66,20 +67,47 @@ type Event struct { // TODO(jbd): Move Sender interface definition to a top-level package. +var ( + // senderMu protects sender. + senderMu sync.Mutex + + // sender is notified with the sensor data each time a new event is available. + sender Sender +) + // Sender sends an event. type Sender interface { Send(event interface{}) } +// Notify registers a Sender and sensor events will be sent to s. +// A typical example of Sender implementations is app.App. +// Once you call Notify, you are not allowed to call it again. +// You cannot call Notify with a nil Sender. +func Notify(s Sender) { + senderMu.Lock() + defer senderMu.Unlock() + + if s == nil { + panic("sensor: cannot set a nil sender") + } + if sender != nil { + panic("sensor: another sender is being notified, cannot set s as the sender") + } + sender = s +} + // Enable enables the specified sensor type with the given delay rate. -// Sensor events will be sent to s, a typical example of Sender -// implementations is app.App. -// Enable is not safe for concurrent use. -func Enable(s Sender, t Type, delay time.Duration) error { +// Users must set a non-nil Sender via Notify before enabling a sensor, +// otherwise an error will be returned. +func Enable(t Type, delay time.Duration) error { if t < 0 || int(t) >= len(sensorNames) { return errors.New("sensor: unknown sensor type") } - return enable(s, t, delay) + if err := validSender(); err != nil { + return err + } + return enable(t, delay) } // Disable disables to feed the manager with the specified sensor. @@ -90,3 +118,13 @@ func Disable(t Type) error { } return disable(t) } + +func validSender() error { + senderMu.Lock() + defer senderMu.Unlock() + + if sender == nil { + return errors.New("sensor: no senders to be notified; cannot enable the sensor") + } + return nil +}