summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2009-11-17 10:25:01 -0800
committerAndreas Huber <andih@google.com>2009-11-17 10:29:32 -0800
commitbe11f392a8b8ff1006cf536350cc8a85f8788ff4 (patch)
treeb01deb5339fb3b15db63fa6d021cce441dfe1be1
parent057eacf4578ac6b90ee18c524670e01445bf2732 (diff)
downloadframeworks_av-be11f392a8b8ff1006cf536350cc8a85f8788ff4.zip
frameworks_av-be11f392a8b8ff1006cf536350cc8a85f8788ff4.tar.gz
frameworks_av-be11f392a8b8ff1006cf536350cc8a85f8788ff4.tar.bz2
Improvements to TimedEventQueue.
Events are now cancelled given their "unique" event_id instead of the event pointer itself (which may be reallocated in place if we're unlucky). Also the ability to cancel multiple events matching a predicate has been added.
-rw-r--r--media/libstagefright/TimedEventQueue.cpp77
-rw-r--r--media/libstagefright/include/TimedEventQueue.h36
2 files changed, 86 insertions, 27 deletions
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
index dd8005c..fa68771 100644
--- a/media/libstagefright/TimedEventQueue.cpp
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -31,7 +31,8 @@
namespace android {
TimedEventQueue::TimedEventQueue()
- : mRunning(false),
+ : mNextEventID(1),
+ mRunning(false),
mStopped(false) {
}
@@ -76,26 +77,29 @@ void TimedEventQueue::stop(bool flush) {
mRunning = false;
}
-void TimedEventQueue::postEvent(const sp<Event> &event) {
+TimedEventQueue::event_id TimedEventQueue::postEvent(const sp<Event> &event) {
// Reserve an earlier timeslot an INT64_MIN to be able to post
// the StopEvent to the absolute head of the queue.
- postTimedEvent(event, INT64_MIN + 1);
+ return postTimedEvent(event, INT64_MIN + 1);
}
-void TimedEventQueue::postEventToBack(const sp<Event> &event) {
- postTimedEvent(event, INT64_MAX);
+TimedEventQueue::event_id TimedEventQueue::postEventToBack(
+ const sp<Event> &event) {
+ return postTimedEvent(event, INT64_MAX);
}
-void TimedEventQueue::postEventWithDelay(
+TimedEventQueue::event_id TimedEventQueue::postEventWithDelay(
const sp<Event> &event, int64_t delay_us) {
CHECK(delay_us >= 0);
- postTimedEvent(event, getRealTimeUs() + delay_us);
+ return postTimedEvent(event, getRealTimeUs() + delay_us);
}
-void TimedEventQueue::postTimedEvent(
+TimedEventQueue::event_id TimedEventQueue::postTimedEvent(
const sp<Event> &event, int64_t realtime_us) {
Mutex::Autolock autoLock(mLock);
+ event->setEventID(mNextEventID++);
+
List<QueueItem>::iterator it = mQueue.begin();
while (it != mQueue.end() && realtime_us >= (*it).realtime_us) {
++it;
@@ -112,29 +116,60 @@ void TimedEventQueue::postTimedEvent(
mQueue.insert(it, item);
mQueueNotEmptyCondition.signal();
-}
-bool TimedEventQueue::cancelEvent(const sp<Event> &event) {
- Mutex::Autolock autoLock(mLock);
+ return event->eventID();
+}
- List<QueueItem>::iterator it = mQueue.begin();
- while (it != mQueue.end() && (*it).event != event) {
- ++it;
- }
+static bool MatchesEventID(
+ void *cookie, const sp<TimedEventQueue::Event> &event) {
+ TimedEventQueue::event_id *id =
+ static_cast<TimedEventQueue::event_id *>(cookie);
- if (it == mQueue.end()) {
+ if (event->eventID() != *id) {
return false;
}
- if (it == mQueue.begin()) {
- mQueueHeadChangedCondition.signal();
- }
-
- mQueue.erase(it);
+ *id = 0;
return true;
}
+bool TimedEventQueue::cancelEvent(event_id id) {
+ CHECK(id != 0);
+
+ cancelEvents(&MatchesEventID, &id, true /* stopAfterFirstMatch */);
+
+ // if MatchesEventID found a match, it will have set id to 0
+ // (which is not a valid event_id).
+
+ return id == 0;
+}
+
+void TimedEventQueue::cancelEvents(
+ bool (*predicate)(void *cookie, const sp<Event> &event),
+ void *cookie,
+ bool stopAfterFirstMatch) {
+ Mutex::Autolock autoLock(mLock);
+
+ List<QueueItem>::iterator it = mQueue.begin();
+ while (it != mQueue.end()) {
+ if (!(*predicate)(cookie, (*it).event)) {
+ ++it;
+ continue;
+ }
+
+ if (it == mQueue.begin()) {
+ mQueueHeadChangedCondition.signal();
+ }
+
+ it = mQueue.erase(it);
+
+ if (stopAfterFirstMatch) {
+ return;
+ }
+ }
+}
+
// static
int64_t TimedEventQueue::getRealTimeUs() {
struct timeval tv;
diff --git a/media/libstagefright/include/TimedEventQueue.h b/media/libstagefright/include/TimedEventQueue.h
index a264421..21eade3 100644
--- a/media/libstagefright/include/TimedEventQueue.h
+++ b/media/libstagefright/include/TimedEventQueue.h
@@ -28,16 +28,31 @@ namespace android {
struct TimedEventQueue {
+ typedef int32_t event_id;
+
struct Event : public RefBase {
- Event() {}
+ Event()
+ : mEventID(0) {
+ }
+
virtual ~Event() {}
+ event_id eventID() {
+ return mEventID;
+ }
+
protected:
virtual void fire(TimedEventQueue *queue, int64_t now_us) = 0;
private:
friend class TimedEventQueue;
+ event_id mEventID;
+
+ void setEventID(event_id id) {
+ mEventID = id;
+ }
+
Event(const Event &);
Event &operator=(const Event &);
};
@@ -55,21 +70,29 @@ struct TimedEventQueue {
// Posts an event to the front of the queue (after all events that
// have previously been posted to the front but before timed events).
- void postEvent(const sp<Event> &event);
+ event_id postEvent(const sp<Event> &event);
- void postEventToBack(const sp<Event> &event);
+ event_id postEventToBack(const sp<Event> &event);
// It is an error to post an event with a negative delay.
- void postEventWithDelay(const sp<Event> &event, int64_t delay_us);
+ event_id postEventWithDelay(const sp<Event> &event, int64_t delay_us);
// If the event is to be posted at a time that has already passed,
// it will fire as soon as possible.
- void postTimedEvent(const sp<Event> &event, int64_t realtime_us);
+ event_id postTimedEvent(const sp<Event> &event, int64_t realtime_us);
// Returns true iff event is currently in the queue and has been
// successfully cancelled. In this case the event will have been
// removed from the queue and won't fire.
- bool cancelEvent(const sp<Event> &event);
+ bool cancelEvent(event_id id);
+
+ // Cancel any pending event that satisfies the predicate.
+ // If stopAfterFirstMatch is true, only cancels the first event
+ // satisfying the predicate (if any).
+ void cancelEvents(
+ bool (*predicate)(void *cookie, const sp<Event> &event),
+ void *cookie,
+ bool stopAfterFirstMatch = false);
static int64_t getRealTimeUs();
@@ -90,6 +113,7 @@ private:
Mutex mLock;
Condition mQueueNotEmptyCondition;
Condition mQueueHeadChangedCondition;
+ event_id mNextEventID;
bool mRunning;
bool mStopped;