summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2010-07-02 18:52:01 -0700
committerDianne Hackborn <hackbod@google.com>2010-07-02 18:57:02 -0700
commitefa10850665c8d60e562f3a488ae65e225614707 (patch)
tree716669410b52fd7dc61aa72926b729c891876c1d /libs
parentbf83375c73f0dcde5d97b36273e3fd971411e866 (diff)
downloadframeworks_native-efa10850665c8d60e562f3a488ae65e225614707.zip
frameworks_native-efa10850665c8d60e562f3a488ae65e225614707.tar.gz
frameworks_native-efa10850665c8d60e562f3a488ae65e225614707.tar.bz2
Add new native Looper API.
This allows us to avoid exposing the file descriptor of the event queue; instead, you attach an event queue to a looper. This will also should allow native apps to be written without the need for a separate thread, by attaching the event queue to the main thread's looper and scheduling their own messages there. Change-Id: I38489282635895ae2cbfacb88599c1b1cad9b239
Diffstat (limited to 'libs')
-rw-r--r--libs/utils/PollLoop.cpp68
1 files changed, 64 insertions, 4 deletions
diff --git a/libs/utils/PollLoop.cpp b/libs/utils/PollLoop.cpp
index 20a4d13..58fe141 100644
--- a/libs/utils/PollLoop.cpp
+++ b/libs/utils/PollLoop.cpp
@@ -21,6 +21,10 @@
namespace android {
+static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
+static bool gHaveTLS = false;
+static pthread_key_t gTLS = 0;
+
PollLoop::PollLoop() :
mPolling(false), mWaiters(0) {
openWakePipe();
@@ -30,6 +34,41 @@ PollLoop::~PollLoop() {
closeWakePipe();
}
+void PollLoop::threadDestructor(void *st) {
+ PollLoop* const self = static_cast<PollLoop*>(st);
+ if (self != NULL) {
+ self->decStrong((void*)threadDestructor);
+ }
+}
+
+void PollLoop::setForThread(const sp<PollLoop>& pollLoop) {
+ sp<PollLoop> old = getForThread();
+
+ if (pollLoop != NULL) {
+ pollLoop->incStrong((void*)threadDestructor);
+ }
+
+ pthread_setspecific(gTLS, pollLoop.get());
+
+ if (old != NULL) {
+ old->decStrong((void*)threadDestructor);
+ }
+}
+
+sp<PollLoop> PollLoop::getForThread() {
+ if (!gHaveTLS) {
+ pthread_mutex_lock(&gTLSMutex);
+ if (pthread_key_create(&gTLS, threadDestructor) != 0) {
+ pthread_mutex_unlock(&gTLSMutex);
+ return NULL;
+ }
+ gHaveTLS = true;
+ pthread_mutex_unlock(&gTLSMutex);
+ }
+
+ return (PollLoop*)pthread_getspecific(gTLS);
+}
+
void PollLoop::openWakePipe() {
int wakeFds[2];
int result = pipe(wakeFds);
@@ -54,6 +93,7 @@ void PollLoop::openWakePipe() {
RequestedCallback requestedCallback;
requestedCallback.callback = NULL;
+ requestedCallback.looperCallback = NULL;
requestedCallback.data = NULL;
mRequestedCallbacks.insertAt(requestedCallback, 0);
}
@@ -123,12 +163,14 @@ bool PollLoop::pollOnce(int timeoutMillis) {
if (revents) {
const RequestedCallback& requestedCallback = mRequestedCallbacks.itemAt(i);
Callback callback = requestedCallback.callback;
+ ALooper_callbackFunc* looperCallback = requestedCallback.looperCallback;
- if (callback) {
+ if (callback || looperCallback) {
PendingCallback pendingCallback;
pendingCallback.fd = requestedFd.fd;
pendingCallback.events = requestedFd.revents;
pendingCallback.callback = callback;
+ pendingCallback.looperCallback = looperCallback;
pendingCallback.data = requestedCallback.data;
mPendingCallbacks.push(pendingCallback);
} else {
@@ -172,8 +214,14 @@ Done:
LOGD("%p ~ pollOnce - invoking callback for fd %d", this, pendingCallback.fd);
#endif
- bool keep = pendingCallback.callback(pendingCallback.fd, pendingCallback.events,
- pendingCallback.data);
+ bool keep = true;
+ if (pendingCallback.callback != NULL) {
+ keep = pendingCallback.callback(pendingCallback.fd, pendingCallback.events,
+ pendingCallback.data);
+ } else {
+ keep = pendingCallback.looperCallback(pendingCallback.fd, pendingCallback.events,
+ pendingCallback.data) != 0;
+ }
if (! keep) {
removeCallback(pendingCallback.fd);
}
@@ -200,11 +248,22 @@ void PollLoop::wake() {
}
void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
+ setCallbackCommon(fd, events, callback, NULL, data);
+}
+
+void PollLoop::setLooperCallback(int fd, int events, ALooper_callbackFunc* callback,
+ void* data) {
+ setCallbackCommon(fd, events, NULL, callback, data);
+}
+
+void PollLoop::setCallbackCommon(int fd, int events, Callback callback,
+ ALooper_callbackFunc* looperCallback, void* data) {
+
#if DEBUG_CALLBACKS
LOGD("%p ~ setCallback - fd=%d, events=%d", this, fd, events);
#endif
- if (! events || ! callback) {
+ if (! events || (! callback && ! looperCallback)) {
LOGE("Invalid attempt to set a callback with no selected poll events or no callback.");
removeCallback(fd);
return;
@@ -218,6 +277,7 @@ void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
RequestedCallback requestedCallback;
requestedCallback.callback = callback;
+ requestedCallback.looperCallback = looperCallback;
requestedCallback.data = data;
ssize_t index = getRequestIndexLocked(fd);