Looper.h revision 54e1cdacd2b132997fdca5e5b90e45855c7a2a95
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// Currently using poll() instead of epoll_wait() since it does a better job of meeting a
28// timeout deadline.  epoll_wait() typically causes additional delays of up to 10ms
29// beyond the requested timeout.
30//#define LOOPER_USES_EPOLL
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 */
42struct ALooper {
43};
44
45namespace 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 */
53class Looper : public ALooper, public RefBase {
54protected:
55    virtual ~Looper();
56
57public:
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);
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);
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
191private:
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