• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef UTILS_LOOPER_H
18 #define UTILS_LOOPER_H
19 
20 #include <utils/threads.h>
21 #include <utils/RefBase.h>
22 #include <utils/KeyedVector.h>
23 #include <utils/Timers.h>
24 
25 #include <android/looper.h>
26 
27 // When defined, uses epoll_wait() for polling, otherwise uses poll().
28 #define LOOPER_USES_EPOLL
29 
30 // When defined, logs performance statistics for tuning and debugging purposes.
31 //#define LOOPER_STATISTICS
32 
33 #ifdef LOOPER_USES_EPOLL
34 #include <sys/epoll.h>
35 #else
36 #include <sys/poll.h>
37 #endif
38 
39 /*
40  * Declare a concrete type for the NDK's looper forward declaration.
41  */
42 struct ALooper {
43 };
44 
45 namespace android {
46 
47 /**
48  * A polling loop that supports monitoring file descriptor events, optionally
49  * using callbacks.  The implementation uses epoll() internally.
50  *
51  * A looper can be associated with a thread although there is no requirement that it must be.
52  */
53 class Looper : public ALooper, public RefBase {
54 protected:
55     virtual ~Looper();
56 
57 public:
58     /**
59      * Creates a looper.
60      *
61      * If allowNonCallbaks is true, the looper will allow file descriptors to be
62      * registered without associated callbacks.  This assumes that the caller of
63      * pollOnce() is prepared to handle callback-less events itself.
64      */
65     Looper(bool allowNonCallbacks);
66 
67     /**
68      * Returns whether this looper instance allows the registration of file descriptors
69      * using identifiers instead of callbacks.
70      */
71     bool getAllowNonCallbacks() const;
72 
73     /**
74      * Waits for events to be available, with optional timeout in milliseconds.
75      * Invokes callbacks for all file descriptors on which an event occurred.
76      *
77      * If the timeout is zero, returns immediately without blocking.
78      * If the timeout is negative, waits indefinitely until an event appears.
79      *
80      * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before
81      * the timeout expired and no callbacks were invoked and no other file
82      * descriptors were ready.
83      *
84      * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked.
85      *
86      * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given
87      * timeout expired.
88      *
89      * Returns ALOOPER_POLL_ERROR if an error occurred.
90      *
91      * Returns a value >= 0 containing an identifier if its file descriptor has data
92      * and it has no callback function (requiring the caller here to handle it).
93      * In this (and only this) case outFd, outEvents and outData will contain the poll
94      * events and data associated with the fd, otherwise they will be set to NULL.
95      *
96      * This method does not return until it has finished invoking the appropriate callbacks
97      * for all file descriptors that were signalled.
98      */
99     int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
pollOnce(int timeoutMillis)100     inline int pollOnce(int timeoutMillis) {
101         return pollOnce(timeoutMillis, NULL, NULL, NULL);
102     }
103 
104     /**
105      * Like pollOnce(), but performs all pending callbacks until all
106      * data has been consumed or a file descriptor is available with no callback.
107      * This function will never return ALOOPER_POLL_CALLBACK.
108      */
109     int pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData);
pollAll(int timeoutMillis)110     inline int pollAll(int timeoutMillis) {
111         return pollAll(timeoutMillis, NULL, NULL, NULL);
112     }
113 
114     /**
115      * Wakes the poll asynchronously.
116      *
117      * This method can be called on any thread.
118      * This method returns immediately.
119      */
120     void wake();
121 
122     /**
123      * Adds a new file descriptor to be polled by the looper.
124      * If the same file descriptor was previously added, it is replaced.
125      *
126      * "fd" is the file descriptor to be added.
127      * "ident" is an identifier for this event, which is returned from ALooper_pollOnce().
128      * The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback.
129      * "events" are the poll events to wake up on.  Typically this is ALOOPER_EVENT_INPUT.
130      * "callback" is the function to call when there is an event on the file descriptor.
131      * "data" is a private data pointer to supply to the callback.
132      *
133      * There are two main uses of this function:
134      *
135      * (1) If "callback" is non-NULL, then this function will be called when there is
136      * data on the file descriptor.  It should execute any events it has pending,
137      * appropriately reading from the file descriptor.  The 'ident' is ignored in this case.
138      *
139      * (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce
140      * when its file descriptor has data available, requiring the caller to take
141      * care of processing it.
142      *
143      * Returns 1 if the file descriptor was added, 0 if the arguments were invalid.
144      *
145      * This method can be called on any thread.
146      * This method may block briefly if it needs to wake the poll.
147      */
148     int addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data);
149 
150     /**
151      * Removes a previously added file descriptor from the looper.
152      *
153      * When this method returns, it is safe to close the file descriptor since the looper
154      * will no longer have a reference to it.  However, it is possible for the callback to
155      * already be running or for it to run one last time if the file descriptor was already
156      * signalled.  Calling code is responsible for ensuring that this case is safely handled.
157      * For example, if the callback takes care of removing itself during its own execution either
158      * by returning 0 or by calling this method, then it can be guaranteed to not be invoked
159      * again at any later time unless registered anew.
160      *
161      * Returns 1 if the file descriptor was removed, 0 if none was previously registered.
162      *
163      * This method can be called on any thread.
164      * This method may block briefly if it needs to wake the poll.
165      */
166     int removeFd(int fd);
167 
168     /**
169      * Prepares a looper associated with the calling thread, and returns it.
170      * If the thread already has a looper, it is returned.  Otherwise, a new
171      * one is created, associated with the thread, and returned.
172      *
173      * The opts may be ALOOPER_PREPARE_ALLOW_NON_CALLBACKS or 0.
174      */
175     static sp<Looper> prepare(int opts);
176 
177     /**
178      * Sets the given looper to be associated with the calling thread.
179      * If another looper is already associated with the thread, it is replaced.
180      *
181      * If "looper" is NULL, removes the currently associated looper.
182      */
183     static void setForThread(const sp<Looper>& looper);
184 
185     /**
186      * Returns the looper associated with the calling thread, or NULL if
187      * there is not one.
188      */
189     static sp<Looper> getForThread();
190 
191 private:
192     struct Request {
193         int fd;
194         int ident;
195         ALooper_callbackFunc callback;
196         void* data;
197     };
198 
199     struct Response {
200         int events;
201         Request request;
202     };
203 
204     const bool mAllowNonCallbacks; // immutable
205 
206     int mWakeReadPipeFd;  // immutable
207     int mWakeWritePipeFd; // immutable
208     Mutex mLock;
209 
210 #ifdef LOOPER_USES_EPOLL
211     int mEpollFd; // immutable
212 
213     // Locked list of file descriptor monitoring requests.
214     KeyedVector<int, Request> mRequests;  // guarded by mLock
215 #else
216     // The lock guards state used to track whether there is a poll() in progress and whether
217     // there are any other threads waiting in wakeAndLock().  The condition variables
218     // are used to transfer control among these threads such that all waiters are
219     // serviced before a new poll can begin.
220     // The wakeAndLock() method increments mWaiters, wakes the poll, blocks on mAwake
221     // until mPolling becomes false, then decrements mWaiters again.
222     // The poll() method blocks on mResume until mWaiters becomes 0, then sets
223     // mPolling to true, blocks until the poll completes, then resets mPolling to false
224     // and signals mResume if there are waiters.
225     bool mPolling;      // guarded by mLock
226     uint32_t mWaiters;  // guarded by mLock
227     Condition mAwake;   // guarded by mLock
228     Condition mResume;  // guarded by mLock
229 
230     Vector<struct pollfd> mRequestedFds;  // must hold mLock and mPolling must be false to modify
231     Vector<Request> mRequests;            // must hold mLock and mPolling must be false to modify
232 
233     ssize_t getRequestIndexLocked(int fd);
234     void wakeAndLock();
235 #endif
236 
237 #ifdef LOOPER_STATISTICS
238     static const int SAMPLED_WAKE_CYCLES_TO_AGGREGATE = 100;
239     static const int SAMPLED_POLLS_TO_AGGREGATE = 1000;
240 
241     nsecs_t mPendingWakeTime;
242     int mPendingWakeCount;
243 
244     int mSampledWakeCycles;
245     int mSampledWakeCountSum;
246     nsecs_t mSampledWakeLatencySum;
247 
248     int mSampledPolls;
249     int mSampledZeroPollCount;
250     int mSampledZeroPollLatencySum;
251     int mSampledTimeoutPollCount;
252     int mSampledTimeoutPollLatencySum;
253 #endif
254 
255     // This state is only used privately by pollOnce and does not require a lock since
256     // it runs on a single thread.
257     Vector<Response> mResponses;
258     size_t mResponseIndex;
259 
260     int pollInner(int timeoutMillis);
261     void awoken();
262     void pushResponse(int events, const Request& request);
263 
264     static void initTLSKey();
265     static void threadDestructor(void *st);
266 };
267 
268 } // namespace android
269 
270 #endif // UTILS_LOOPER_H
271