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 <nigeltao@golang.org>
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 <android/sensor.h>
 
-#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 @@
   // 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 @@
   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 @@
 #include <stdlib.h>
 #include <android/sensor.h>
 
-#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 @@
 	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 @@
 	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 @@
 		}
 	}()
 
-	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 @@
 	return err
 }
 
-func (m *manager) startCollecting(s Sender) {
+func startCollecting(s Sender) {
 	collectingMu.Lock()
 	defer collectingMu.Unlock()
 
@@ -159,7 +149,7 @@
 			// 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) 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 @@
 	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(&timestamps[0])),
@@ -208,10 +197,10 @@
 	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 @@
 	done [nTypes]chan struct{}
 }
 
-type manager struct {
-}
-
-func (m *manager) initialize() {
+func init() {
 	C.GoIOS_createManager()
 }
 
@@ -63,7 +60,7 @@
 
 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 @@
 	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 @@
 	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 @@
 	}
 }
 
-// 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 @@
 	"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 @@
 
 var sensorNames = map[Type]string{
 	Accelerometer: "Accelerometer",
-	Gyroscope:     "Gyrsocope",
+	Gyroscope:     "Gyroscope",
 	Magnetometer:  "Magnetometer",
 }
 
@@ -71,9 +71,6 @@
 	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 @@
 	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 @@
 	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)
 }