diff options
author | Jeff Brown <jeffbrown@google.com> | 2010-09-14 15:27:33 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-09-14 15:27:33 -0700 |
commit | b06cca6228aec6acfefbfae7edd768d7de4c7057 (patch) | |
tree | 3b8867c86e546dd0dea4f356389a46bd084e7d6b /include | |
parent | 959d007a864786bd99569c27b84e42aaf9d1507e (diff) | |
parent | 59abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8a (diff) | |
download | frameworks_native-b06cca6228aec6acfefbfae7edd768d7de4c7057.zip frameworks_native-b06cca6228aec6acfefbfae7edd768d7de4c7057.tar.gz frameworks_native-b06cca6228aec6acfefbfae7edd768d7de4c7057.tar.bz2 |
Merge "Replace epoll() with poll() and rename PollLoop to Looper." into gingerbread
Diffstat (limited to 'include')
-rw-r--r-- | include/gui/SensorEventQueue.h | 6 | ||||
-rw-r--r-- | include/ui/InputDispatcher.h | 8 | ||||
-rw-r--r-- | include/ui/InputTransport.h | 1 | ||||
-rw-r--r-- | include/utils/Looper.h | 210 | ||||
-rw-r--r-- | include/utils/PollLoop.h | 219 |
5 files changed, 217 insertions, 227 deletions
diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h index 6581ae3..97dd391 100644 --- a/include/gui/SensorEventQueue.h +++ b/include/gui/SensorEventQueue.h @@ -42,7 +42,7 @@ namespace android { class ISensorEventConnection; class Sensor; -class PollLoop; +class Looper; // ---------------------------------------------------------------------------- @@ -69,11 +69,11 @@ public: status_t disableSensor(int32_t handle) const; private: - sp<PollLoop> getPollLoop() const; + sp<Looper> getLooper() const; sp<ISensorEventConnection> mSensorEventConnection; sp<SensorChannel> mSensorChannel; mutable Mutex mLock; - mutable sp<PollLoop> mPollLoop; + mutable sp<Looper> mLooper; }; // ---------------------------------------------------------------------------- diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h index a06208a..d7e6254 100644 --- a/include/ui/InputDispatcher.h +++ b/include/ui/InputDispatcher.h @@ -25,7 +25,7 @@ #include <utils/Timers.h> #include <utils/RefBase.h> #include <utils/String8.h> -#include <utils/PollLoop.h> +#include <utils/Looper.h> #include <utils/Pool.h> #include <stddef.h> @@ -826,7 +826,7 @@ private: Mutex mLock; Allocator mAllocator; - sp<PollLoop> mPollLoop; + sp<Looper> mLooper; EventEntry* mPendingEvent; Queue<EventEntry> mInboundQueue; @@ -837,7 +837,7 @@ private: void dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime); - // Enqueues an inbound event. Returns true if mPollLoop->wake() should be called. + // Enqueues an inbound event. Returns true if mLooper->wake() should be called. bool enqueueInboundEventLocked(EventEntry* entry); // App switch latency optimization. @@ -1010,7 +1010,7 @@ private: void abortDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, bool broken); void drainOutboundQueueLocked(Connection* connection, DispatchEntry* firstDispatchEntryToDrain); - static bool handleReceiveCallback(int receiveFd, int events, void* data); + static int handleReceiveCallback(int receiveFd, int events, void* data); // Preempting input dispatch. bool preemptInputDispatchInnerLocked(); diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h index 82831e2..dc9e27a 100644 --- a/include/ui/InputTransport.h +++ b/include/ui/InputTransport.h @@ -33,7 +33,6 @@ #include <semaphore.h> #include <ui/Input.h> #include <utils/Errors.h> -#include <utils/PollLoop.h> #include <utils/Timers.h> #include <utils/RefBase.h> #include <utils/String8.h> diff --git a/include/utils/Looper.h b/include/utils/Looper.h new file mode 100644 index 0000000..92e4b0a --- /dev/null +++ b/include/utils/Looper.h @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UTILS_LOOPER_H +#define UTILS_LOOPER_H + +#include <utils/threads.h> +#include <utils/RefBase.h> +#include <utils/KeyedVector.h> + +#include <android/looper.h> + +/* + * Declare a concrete type for the NDK's looper forward declaration. + */ +struct ALooper { +}; + +namespace android { + +/** + * A polling loop that supports monitoring file descriptor events, optionally + * using callbacks. The implementation uses epoll() internally. + * + * A looper can be associated with a thread although there is no requirement that it must be. + */ +class Looper : public ALooper, public RefBase { +protected: + virtual ~Looper(); + +public: + /** + * Creates a looper. + * + * If allowNonCallbaks is true, the looper will allow file descriptors to be + * registered without associated callbacks. This assumes that the caller of + * pollOnce() is prepared to handle callback-less events itself. + */ + Looper(bool allowNonCallbacks); + + /** + * Returns whether this looper instance allows the registration of file descriptors + * using identifiers instead of callbacks. + */ + bool getAllowNonCallbacks() const; + + /** + * Waits for events to be available, with optional timeout in milliseconds. + * Invokes callbacks for all file descriptors on which an event occurred. + * + * If the timeout is zero, returns immediately without blocking. + * If the timeout is negative, waits indefinitely until an event appears. + * + * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before + * the timeout expired and no callbacks were invoked and no other file + * descriptors were ready. + * + * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked. + * + * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given + * timeout expired. + * + * Returns ALOOPER_POLL_ERROR if an error occurred. + * + * Returns a value >= 0 containing an identifier if its file descriptor has data + * and it has no callback function (requiring the caller here to handle it). + * In this (and only this) case outFd, outEvents and outData will contain the poll + * events and data associated with the fd, otherwise they will be set to NULL. + * + * This method does not return until it has finished invoking the appropriate callbacks + * for all file descriptors that were signalled. + */ + int pollOnce(int timeoutMillis, + int* outFd = NULL, int* outEvents = NULL, void** outData = NULL); + + /** + * Like pollOnce(), but performs all pending callbacks until all + * data has been consumed or a file descriptor is available with no callback. + * This function will never return ALOOPER_POLL_CALLBACK. + */ + int pollAll(int timeoutMillis, + int* outFd = NULL, int* outEvents = NULL, void** outData = NULL); + + /** + * Wakes the poll asynchronously. + * + * This method can be called on any thread. + * This method returns immediately. + */ + void wake(); + + /** + * Adds a new file descriptor to be polled by the looper. + * If the same file descriptor was previously added, it is replaced. + * + * "fd" is the file descriptor to be added. + * "ident" is an identifier for this event, which is returned from ALooper_pollOnce(). + * The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback. + * "events" are the poll events to wake up on. Typically this is ALOOPER_EVENT_INPUT. + * "callback" is the function to call when there is an event on the file descriptor. + * "data" is a private data pointer to supply to the callback. + * + * There are two main uses of this function: + * + * (1) If "callback" is non-NULL, then this function will be called when there is + * data on the file descriptor. It should execute any events it has pending, + * appropriately reading from the file descriptor. The 'ident' is ignored in this case. + * + * (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce + * when its file descriptor has data available, requiring the caller to take + * care of processing it. + * + * Returns 1 if the file descriptor was added, 0 if the arguments were invalid. + * + * This method can be called on any thread. + * This method may block briefly if it needs to wake the poll. + */ + int addFd(int fd, int ident, + int events, ALooper_callbackFunc callback, void* data = NULL); + + /** + * Removes a previously added file descriptor from the looper. + * + * When this method returns, it is safe to close the file descriptor since the looper + * will no longer have a reference to it. However, it is possible for the callback to + * already be running or for it to run one last time if the file descriptor was already + * signalled. Calling code is responsible for ensuring that this case is safely handled. + * For example, if the callback takes care of removing itself during its own execution either + * by returning 0 or by calling this method, then it can be guaranteed to not be invoked + * again at any later time unless registered anew. + * + * Returns 1 if the file descriptor was removed, 0 if none was previously registered. + * + * This method can be called on any thread. + * This method may block briefly if it needs to wake the poll. + */ + int removeFd(int fd); + + /** + * Prepares a looper associated with the calling thread, and returns it. + * If the thread already has a looper, it is returned. Otherwise, a new + * one is created, associated with the thread, and returned. + * + * The opts may be ALOOPER_PREPARE_ALLOW_NON_CALLBACKS or 0. + */ + static sp<Looper> prepare(int opts); + + /** + * Sets the given looper to be associated with the calling thread. + * If another looper is already associated with the thread, it is replaced. + * + * If "looper" is NULL, removes the currently associated looper. + */ + static void setForThread(const sp<Looper>& looper); + + /** + * Returns the looper associated with the calling thread, or NULL if + * there is not one. + */ + static sp<Looper> getForThread(); + +private: + struct Request { + int fd; + int ident; + ALooper_callbackFunc callback; + void* data; + }; + + struct Response { + int events; + Request request; + }; + + const bool mAllowNonCallbacks; // immutable + + int mEpollFd; // immutable + int mWakeReadPipeFd; // immutable + int mWakeWritePipeFd; // immutable + + // Locked list of file descriptor monitoring requests. + Mutex mLock; + KeyedVector<int, Request> mRequests; + + // This state is only used privately by pollOnce and does not require a lock since + // it runs on a single thread. + Vector<Response> mResponses; + size_t mResponseIndex; + + int pollInner(int timeoutMillis); + + static void threadDestructor(void *st); +}; + +} // namespace android + +#endif // UTILS_LOOPER_H diff --git a/include/utils/PollLoop.h b/include/utils/PollLoop.h deleted file mode 100644 index c2dfe5d..0000000 --- a/include/utils/PollLoop.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef UTILS_POLL_LOOP_H -#define UTILS_POLL_LOOP_H - -#include <utils/Vector.h> -#include <utils/threads.h> - -#include <sys/poll.h> - -#include <android/looper.h> - -struct ALooper : public android::RefBase { -protected: - virtual ~ALooper() { } - -public: - ALooper() { } -}; - -namespace android { - -/** - * A basic file descriptor polling loop based on poll() with callbacks. - */ -class PollLoop : public ALooper { -protected: - virtual ~PollLoop(); - -public: - PollLoop(bool allowNonCallbacks); - - /** - * A callback that it to be invoked when an event occurs on a file descriptor. - * Specifies the events that were triggered and the user data provided when the - * callback was set. - * - * Returns true if the callback should be kept, false if it should be removed automatically - * after the callback returns. - */ - typedef bool (*Callback)(int fd, int events, void* data); - - enum { - POLL_CALLBACK = ALOOPER_POLL_CALLBACK, - POLL_TIMEOUT = ALOOPER_POLL_TIMEOUT, - POLL_ERROR = ALOOPER_POLL_ERROR, - }; - - /** - * Performs a single call to poll() with optional timeout in milliseconds. - * Invokes callbacks for all file descriptors on which an event occurred. - * - * If the timeout is zero, returns immediately without blocking. - * If the timeout is negative, waits indefinitely until awoken. - * - * Returns ALOOPER_POLL_CALLBACK if a callback was invoked. - * - * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given - * timeout expired. - * - * Returns ALOPER_POLL_ERROR if an error occurred. - * - * Returns a value >= 0 containing a file descriptor if it has data - * and it has no callback function (requiring the caller here to handle it). - * In this (and only this) case outEvents and outData will contain the poll - * events and data associated with the fd. - * - * This method must only be called on the thread owning the PollLoop. - * This method blocks until either a file descriptor is signalled, a timeout occurs, - * or wake() is called. - * This method does not return until it has finished invoking the appropriate callbacks - * for all file descriptors that were signalled. - */ - int32_t pollOnce(int timeoutMillis, int* outEvents = NULL, void** outData = NULL); - - /** - * Wakes the loop asynchronously. - * - * This method can be called on any thread. - * This method returns immediately. - */ - void wake(); - - /** - * Control whether this PollLoop instance allows using IDs instead - * of callbacks. - */ - bool getAllowNonCallbacks() const; - - /** - * Sets the callback for a file descriptor, replacing the existing one, if any. - * It is an error to call this method with events == 0 or callback == NULL. - * - * Note that a callback can be invoked with the POLLERR, POLLHUP or POLLNVAL events - * even if it is not explicitly requested when registered. - * - * This method can be called on any thread. - * This method may block briefly if it needs to wake the poll loop. - */ - void setCallback(int fd, int ident, int events, Callback callback, void* data = NULL); - - /** - * Convenience for above setCallback when ident is not used. In this case - * the ident is set to POLL_CALLBACK. - */ - void setCallback(int fd, int events, Callback callback, void* data = NULL); - - /** - * Like setCallback(), but for the NDK callback function. - */ - void setLooperCallback(int fd, int ident, int events, ALooper_callbackFunc* callback, - void* data); - - /** - * Removes the callback for a file descriptor, if one exists. - * - * When this method returns, it is safe to close the file descriptor since the poll loop - * will no longer have a reference to it. However, it is possible for the callback to - * already be running or for it to run one last time if the file descriptor was already - * signalled. Calling code is responsible for ensuring that this case is safely handled. - * For example, if the callback takes care of removing itself during its own execution either - * by returning false or calling this method, then it can be guaranteed to not be invoked - * again at any later time unless registered anew. - * - * This method can be called on any thread. - * This method may block briefly if it needs to wake the poll loop. - * - * Returns true if a callback was actually removed, false if none was registered. - */ - bool removeCallback(int fd); - - /** - * Set the given PollLoop to be associated with the - * calling thread. There must be a 1:1 relationship between - * PollLoop and thread. - */ - static void setForThread(const sp<PollLoop>& pollLoop); - - /** - * Return the PollLoop associated with the calling thread. - */ - static sp<PollLoop> getForThread(); - -private: - struct RequestedCallback { - Callback callback; - ALooper_callbackFunc* looperCallback; - int ident; - void* data; - }; - - struct PendingCallback { - int fd; - int ident; - int events; - Callback callback; - ALooper_callbackFunc* looperCallback; - void* data; - }; - - const bool mAllowNonCallbacks; // immutable - - int mWakeReadPipeFd; // immutable - int mWakeWritePipeFd; // immutable - - // The lock guards state used to track whether there is a poll() in progress and whether - // there are any other threads waiting in wakeAndLock(). The condition variables - // are used to transfer control among these threads such that all waiters are - // serviced before a new poll can begin. - // The wakeAndLock() method increments mWaiters, wakes the poll, blocks on mAwake - // until mPolling becomes false, then decrements mWaiters again. - // The poll() method blocks on mResume until mWaiters becomes 0, then sets - // mPolling to true, blocks until the poll completes, then resets mPolling to false - // and signals mResume if there are waiters. - Mutex mLock; - bool mPolling; // guarded by mLock - uint32_t mWaiters; // guarded by mLock - Condition mAwake; // guarded by mLock - Condition mResume; // guarded by mLock - - // The next two vectors are only mutated when mPolling is false since they must - // not be changed while the poll() system call is in progress. To mutate these - // vectors, the poll() must first be awoken then the lock acquired. - Vector<struct pollfd> mRequestedFds; - Vector<RequestedCallback> mRequestedCallbacks; - - // This state is only used privately by pollOnce and does not require a lock since - // it runs on a single thread. - Vector<PendingCallback> mPendingCallbacks; - Vector<PendingCallback> mPendingFds; - size_t mPendingFdsPos; - - void openWakePipe(); - void closeWakePipe(); - - void setCallbackCommon(int fd, int ident, int events, Callback callback, - ALooper_callbackFunc* looperCallback, void* data); - ssize_t getRequestIndexLocked(int fd); - void wakeAndLock(); - static void threadDestructor(void *st); -}; - -} // namespace android - -#endif // UTILS_POLL_LOOP_H |