1/*
2 * Copyright (C) 2009 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 TIMED_EVENT_QUEUE_H_
18
19#define TIMED_EVENT_QUEUE_H_
20
21#include <pthread.h>
22
23#include <utils/List.h>
24#include <utils/RefBase.h>
25#include <utils/threads.h>
26
27namespace android {
28
29struct TimedEventQueue {
30
31    typedef int32_t event_id;
32
33    struct Event : public RefBase {
34        Event()
35            : mEventID(0) {
36        }
37
38        virtual ~Event() {}
39
40        event_id eventID() {
41            return mEventID;
42        }
43
44    protected:
45        virtual void fire(TimedEventQueue *queue, int64_t now_us) = 0;
46
47    private:
48        friend class TimedEventQueue;
49
50        event_id mEventID;
51
52        void setEventID(event_id id) {
53            mEventID = id;
54        }
55
56        Event(const Event &);
57        Event &operator=(const Event &);
58    };
59
60    TimedEventQueue();
61    ~TimedEventQueue();
62
63    // Start executing the event loop.
64    void start();
65
66    // Stop executing the event loop, if flush is false, any pending
67    // events are discarded, otherwise the queue will stop (and this call
68    // return) once all pending events have been handled.
69    void stop(bool flush = false);
70
71    // Posts an event to the front of the queue (after all events that
72    // have previously been posted to the front but before timed events).
73    event_id postEvent(const sp<Event> &event);
74
75    event_id postEventToBack(const sp<Event> &event);
76
77    // It is an error to post an event with a negative delay.
78    event_id postEventWithDelay(const sp<Event> &event, int64_t delay_us);
79
80    // If the event is to be posted at a time that has already passed,
81    // it will fire as soon as possible.
82    event_id postTimedEvent(const sp<Event> &event, int64_t realtime_us);
83
84    // Returns true iff event is currently in the queue and has been
85    // successfully cancelled. In this case the event will have been
86    // removed from the queue and won't fire.
87    bool cancelEvent(event_id id);
88
89    // Cancel any pending event that satisfies the predicate.
90    // If stopAfterFirstMatch is true, only cancels the first event
91    // satisfying the predicate (if any).
92    void cancelEvents(
93            bool (*predicate)(void *cookie, const sp<Event> &event),
94            void *cookie,
95            bool stopAfterFirstMatch = false);
96
97    static int64_t getRealTimeUs();
98
99private:
100    struct QueueItem {
101        sp<Event> event;
102        int64_t realtime_us;
103    };
104
105    struct StopEvent : public TimedEventQueue::Event {
106        virtual void fire(TimedEventQueue *queue, int64_t now_us) {
107            queue->mStopped = true;
108        }
109    };
110
111    pthread_t mThread;
112    List<QueueItem> mQueue;
113    Mutex mLock;
114    Condition mQueueNotEmptyCondition;
115    Condition mQueueHeadChangedCondition;
116    event_id mNextEventID;
117
118    bool mRunning;
119    bool mStopped;
120
121    static void *ThreadWrapper(void *me);
122    void threadEntry();
123
124    sp<Event> removeEventFromQueue_l(event_id id);
125
126    TimedEventQueue(const TimedEventQueue &);
127    TimedEventQueue &operator=(const TimedEventQueue &);
128};
129
130}  // namespace android
131
132#endif  // TIMED_EVENT_QUEUE_H_
133