From c76d5c883041844069b52389d6523bdbbaf5694f Mon Sep 17 00:00:00 2001 From: Burcu Dogan Date: Fri, 4 Sep 2015 00:17:01 -0700 Subject: [PATCH] exp/sensor: remove the manager type The manager type is not required, because the APIs don't allow more than one event sources as they used to. In this CL, I am flattening out the underlying implementations by removing the manager type. Change-Id: I3b606ac160b9cecd85cb657e3df1d7d789604764 Reviewed-on: https://go-review.googlesource.com/14293 Reviewed-by: Nigel Tao --- exp/sensor/android.c | 37 ++++++++++---------- exp/sensor/android.go | 71 +++++++++++++++++---------------------- exp/sensor/android.h | 22 ------------ exp/sensor/darwin_armx.go | 17 ++++------ exp/sensor/notmobile.go | 10 ++---- exp/sensor/sensor.go | 17 ++-------- 6 files changed, 61 insertions(+), 113 deletions(-) delete mode 100644 exp/sensor/android.h diff --git a/exp/sensor/android.c b/exp/sensor/android.c index 258b10b..dfe4bbf 100644 --- a/exp/sensor/android.c +++ b/exp/sensor/android.c @@ -9,39 +9,38 @@ #include -#include "android.h" +#define GO_ANDROID_SENSOR_LOOPER_ID 100 -void GoAndroid_createManager(int looperId, GoAndroid_SensorManager* dst) { +ASensorEventQueue* queue = NULL; +ALooper* looper = NULL; + +void GoAndroid_createManager() { ASensorManager* manager = ASensorManager_getInstance(); - - ALooper* looper = ALooper_forThread(); + looper = ALooper_forThread(); if (looper == NULL) { looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); } - ASensorEventQueue* queue = ASensorManager_createEventQueue(manager, looper, looperId, NULL, NULL); - dst->looper = looper; - dst->queue = queue; - dst->looperId = looperId; + queue = ASensorManager_createEventQueue(manager, looper, GO_ANDROID_SENSOR_LOOPER_ID, NULL, NULL); } -int GoAndroid_enableSensor(ASensorEventQueue* q, int s, int32_t usec) { +int GoAndroid_enableSensor(int s, int32_t usec) { ASensorManager* manager = ASensorManager_getInstance(); const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s); if (sensor == NULL) { return 1; } - ASensorEventQueue_enableSensor(q, sensor); - ASensorEventQueue_setEventRate(q, sensor, usec); + ASensorEventQueue_enableSensor(queue, sensor); + ASensorEventQueue_setEventRate(queue, sensor, usec); return 0; } -void GoAndroid_disableSensor(ASensorEventQueue* q, int s) { +void GoAndroid_disableSensor(int s) { ASensorManager* manager = ASensorManager_getInstance(); const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s); - ASensorEventQueue_disableSensor(q, sensor); + ASensorEventQueue_disableSensor(queue, sensor); } -int GoAndroid_readQueue(int looperId, ASensorEventQueue* q, int n, int32_t* types, int64_t* timestamps, float* vectors) { +int GoAndroid_readQueue(int n, int32_t* types, int64_t* timestamps, float* vectors) { int id; int events; ASensorEvent event; @@ -50,10 +49,10 @@ int GoAndroid_readQueue(int looperId, ASensorEventQueue* q, int n, int32_t* type // If anytime timeout occurs, don't retry to read and immediately return. // Consume the event queue entirely between polls. while (i < n && (id = ALooper_pollAll(-1, NULL, &events, NULL)) >= 0) { - if (id != looperId) { + if (id != GO_ANDROID_SENSOR_LOOPER_ID) { continue; } - while (i < n && ASensorEventQueue_getEvents(q, &event, 1)) { + while (i < n && ASensorEventQueue_getEvents(queue, &event, 1)) { types[i] = event.type; timestamps[i] = event.timestamp; vectors[i*3] = event.vector.x; @@ -65,8 +64,8 @@ int GoAndroid_readQueue(int looperId, ASensorEventQueue* q, int n, int32_t* type return i; } -void GoAndroid_destroyManager(GoAndroid_SensorManager* m) { +void GoAndroid_destroyManager() { ASensorManager* manager = ASensorManager_getInstance(); - ASensorManager_destroyEventQueue(manager, m->queue); - ALooper_release(m->looper); + ASensorManager_destroyEventQueue(manager, queue); + ALooper_release(looper); } diff --git a/exp/sensor/android.go b/exp/sensor/android.go index d110cbf..bfb257a 100644 --- a/exp/sensor/android.go +++ b/exp/sensor/android.go @@ -12,14 +12,17 @@ package sensor #include #include -#include "android.h" +void GoAndroid_createManager(); +void GoAndroid_destroyManager(); +int GoAndroid_enableSensor(int, int32_t); +void GoAndroid_disableSensor(int); +int GoAndroid_readQueue(int n, int32_t* types, int64_t* timestamps, float* vectors); */ import "C" import ( "fmt" "runtime" "sync" - "sync/atomic" "time" "unsafe" ) @@ -32,8 +35,6 @@ var ( collecting bool ) -var nextLooperID int64 // each underlying ALooper should have a unique ID. - // initSignal initializes an underlying looper and event queue. type initSignal struct{} @@ -69,43 +70,34 @@ type inOut struct { out chan struct{} } -// manager is the Android-specific implementation of Manager. -type manager struct { - m *C.GoAndroid_SensorManager - inout chan inOut -} +var inout = make(chan inOut) -// initialize inits the manager and creates a goroutine to proxy the CGO calls. +// init inits the manager and creates a goroutine to proxy the CGO calls. // All actions related to an ALooper needs to be performed from the same // OS thread. The goroutine proxy locks itself to an OS thread and handles the // CGO traffic on the same thread. -func (m *manager) initialize() { - m.inout = make(chan inOut) - +func init() { go func() { runtime.LockOSThread() for { - v := <-m.inout + v := <-inout switch s := v.in.(type) { case initSignal: - id := atomic.AddInt64(&nextLooperID, 1) - var mgr C.GoAndroid_SensorManager - C.GoAndroid_createManager(C.int(id), &mgr) - m.m = &mgr + C.GoAndroid_createManager() case enableSignal: usecsDelay := s.delay.Nanoseconds() / 1000 - code := int(C.GoAndroid_enableSensor(m.m.queue, typeToInt(s.t), C.int32_t(usecsDelay))) + code := int(C.GoAndroid_enableSensor(typeToInt(s.t), C.int32_t(usecsDelay))) if code != 0 { *s.err = fmt.Errorf("sensor: no default %v sensor on the device", s.t) } case disableSignal: - C.GoAndroid_disableSensor(m.m.queue, typeToInt(s.t)) + C.GoAndroid_disableSensor(typeToInt(s.t)) case readSignal: - n, err := readEvents(m, s.dst) + n, err := readEvents(s.dst) *s.n = n *s.err = err case closeSignal: - C.GoAndroid_destroyManager(m.m) + C.GoAndroid_destroyManager() close(v.out) return // we don't need this goroutine anymore } @@ -113,22 +105,20 @@ func (m *manager) initialize() { } }() - if m.m == nil { - done := make(chan struct{}) - m.inout <- inOut{ - in: initSignal{}, - out: done, - } - <-done + done := make(chan struct{}) + inout <- inOut{ + in: initSignal{}, + out: done, } + <-done } -func (m *manager) enable(s Sender, t Type, delay time.Duration) error { - m.startCollecting(s) +func enable(s Sender, t Type, delay time.Duration) error { + startCollecting(s) var err error done := make(chan struct{}) - m.inout <- inOut{ + inout <- inOut{ in: enableSignal{t: t, delay: delay, err: &err}, out: done, } @@ -136,7 +126,7 @@ func (m *manager) enable(s Sender, t Type, delay time.Duration) error { return err } -func (m *manager) startCollecting(s Sender) { +func startCollecting(s Sender) { collectingMu.Lock() defer collectingMu.Unlock() @@ -159,7 +149,7 @@ func (m *manager) startCollecting(s Sender) { // TODO(jbd): readSignal is not required anymore. Use the proxying // goroutine to continously poll the queue and send the events to s. done := make(chan struct{}) - m.inout <- inOut{ + inout <- inOut{ in: readSignal{dst: ev, n: &n, err: &err}, out: done, } @@ -171,9 +161,9 @@ func (m *manager) startCollecting(s Sender) { }() } -func (m *manager) disable(t Type) error { +func disable(t Type) error { done := make(chan struct{}) - m.inout <- inOut{ + inout <- inOut{ in: disableSignal{t: t}, out: done, } @@ -181,14 +171,13 @@ func (m *manager) disable(t Type) error { return nil } -func readEvents(m *manager, e []Event) (n int, err error) { +func readEvents(e []Event) (n int, err error) { num := len(e) types := make([]C.int32_t, num) timestamps := make([]C.int64_t, num) vectors := make([]C.float, 3*num) n = int(C.GoAndroid_readQueue( - m.m.looperId, m.m.queue, C.int(num), (*C.int32_t)(unsafe.Pointer(&types[0])), (*C.int64_t)(unsafe.Pointer(×tamps[0])), @@ -208,10 +197,10 @@ func readEvents(m *manager, e []Event) (n int, err error) { return } -// TODO(jbd): Remove close? -func (m *manager) close() error { +// TODO(jbd): Remove destroy? +func destroy() error { done := make(chan struct{}) - m.inout <- inOut{ + inout <- inOut{ in: closeSignal{}, out: done, } diff --git a/exp/sensor/android.h b/exp/sensor/android.h deleted file mode 100644 index c7a452f..0000000 --- a/exp/sensor/android.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build android - -#ifndef GO_SENSORS_ANDROID_H -#define GO_SENSORS_ANDROID_H - -typedef struct GoAndroid_SensorManager { - ASensorEventQueue* queue; - ALooper* looper; - int looperId; -} GoAndroid_SensorManager; - -void GoAndroid_createManager(int looperId, GoAndroid_SensorManager* dst); -void GoAndroid_destroyManager(GoAndroid_SensorManager* m); -int GoAndroid_enableSensor(ASensorEventQueue*, int, int32_t); -void GoAndroid_disableSensor(ASensorEventQueue*, int); -int GoAndroid_readQueue(int looperId, ASensorEventQueue* q, int n, int32_t* types, int64_t* timestamps, float* vectors); - -#endif diff --git a/exp/sensor/darwin_armx.go b/exp/sensor/darwin_armx.go index 94c3f89..c6a54b2 100644 --- a/exp/sensor/darwin_armx.go +++ b/exp/sensor/darwin_armx.go @@ -42,10 +42,7 @@ var channels struct { done [nTypes]chan struct{} } -type manager struct { -} - -func (m *manager) initialize() { +func init() { C.GoIOS_createManager() } @@ -63,7 +60,7 @@ func (m *manager) initialize() { const minDelay = 10 * time.Millisecond -func (m *manager) enable(s Sender, t Type, delay time.Duration) error { +func enable(s Sender, t Type, delay time.Duration) error { channels.Lock() defer channels.Unlock() @@ -85,11 +82,11 @@ func (m *manager) enable(s Sender, t Type, delay time.Duration) error { case Magnetometer: C.GoIOS_startMagneto(interval) } - go m.pollSensor(s, t, delay, channels.done[t]) + go pollSensor(s, t, delay, channels.done[t]) return nil } -func (m *manager) disable(t Type) error { +func disable(t Type) error { channels.Lock() defer channels.Unlock() @@ -110,7 +107,7 @@ func (m *manager) disable(t Type) error { return nil } -func (m *manager) pollSensor(s Sender, t Type, d time.Duration, done chan struct{}) { +func pollSensor(s Sender, t Type, d time.Duration, done chan struct{}) { var lastTimestamp int64 var timestamp C.int64_t @@ -148,8 +145,8 @@ func (m *manager) pollSensor(s Sender, t Type, d time.Duration, done chan struct } } -// TODO(jbd): Remove close? -func (m *manager) close() error { +// TODO(jbd): Remove destroy? +func destroy() error { C.GoIOS_destroyManager() return nil } diff --git a/exp/sensor/notmobile.go b/exp/sensor/notmobile.go index dabc3d2..ee1636a 100644 --- a/exp/sensor/notmobile.go +++ b/exp/sensor/notmobile.go @@ -11,18 +11,14 @@ import ( "time" ) -type manager struct{} - -func (m *manager) initialize() {} - -func (m *manager) enable(s Sender, t Type, delay time.Duration) error { +func enable(s Sender, t Type, delay time.Duration) error { return errors.New("sensor: no sensors available") } -func (m *manager) disable(t Type) error { +func disable(t Type) error { return errors.New("sensor: no sensors available") } -func (m *manager) close() error { +func destroy() error { return nil } diff --git a/exp/sensor/sensor.go b/exp/sensor/sensor.go index eea4e83..74d1ae1 100644 --- a/exp/sensor/sensor.go +++ b/exp/sensor/sensor.go @@ -15,7 +15,7 @@ type Type int var sensorNames = map[Type]string{ Accelerometer: "Accelerometer", - Gyroscope: "Gyrsocope", + Gyroscope: "Gyroscope", Magnetometer: "Magnetometer", } @@ -71,9 +71,6 @@ type Sender interface { Send(event interface{}) } -// m is the underlying platform-specific sensor manager. -var m = newManager() - // 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. @@ -82,7 +79,7 @@ func Enable(s Sender, t Type, delay time.Duration) error { if t < 0 || int(t) >= len(sensorNames) { return errors.New("sensor: unknown sensor type") } - return m.enable(s, t, delay) + return enable(s, t, delay) } // Disable disables to feed the manager with the specified sensor. @@ -91,13 +88,5 @@ func Disable(t Type) error { if t < 0 || int(t) >= len(sensorNames) { return errors.New("sensor: unknown sensor type") } - return m.disable(t) -} - -func newManager() *manager { - // TODO(jbd): manager type is unnecessary, flatten out the - // platform specific implementation. - mgr := new(manager) - mgr.initialize() - return mgr + return disable(t) }