Loading media/libstagefright/TimedEventQueue.cpp +56 −21 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ namespace android { TimedEventQueue::TimedEventQueue() : mRunning(false), : mNextEventID(1), mRunning(false), mStopped(false) { } Loading Loading @@ -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; Loading @@ -112,27 +116,58 @@ void TimedEventQueue::postTimedEvent( mQueue.insert(it, item); mQueueNotEmptyCondition.signal(); return event->eventID(); } static bool MatchesEventID( void *cookie, const sp<TimedEventQueue::Event> &event) { TimedEventQueue::event_id *id = static_cast<TimedEventQueue::event_id *>(cookie); if (event->eventID() != *id) { return false; } bool TimedEventQueue::cancelEvent(const sp<Event> &event) { *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() && (*it).event != event) { while (it != mQueue.end()) { if (!(*predicate)(cookie, (*it).event)) { ++it; } if (it == mQueue.end()) { return false; continue; } if (it == mQueue.begin()) { mQueueHeadChangedCondition.signal(); } mQueue.erase(it); it = mQueue.erase(it); return true; if (stopAfterFirstMatch) { return; } } } // static Loading media/libstagefright/include/TimedEventQueue.h +30 −6 Original line number Diff line number Diff line Loading @@ -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 &); }; Loading @@ -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(); Loading @@ -90,6 +113,7 @@ private: Mutex mLock; Condition mQueueNotEmptyCondition; Condition mQueueHeadChangedCondition; event_id mNextEventID; bool mRunning; bool mStopped; Loading Loading
media/libstagefright/TimedEventQueue.cpp +56 −21 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ namespace android { TimedEventQueue::TimedEventQueue() : mRunning(false), : mNextEventID(1), mRunning(false), mStopped(false) { } Loading Loading @@ -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; Loading @@ -112,27 +116,58 @@ void TimedEventQueue::postTimedEvent( mQueue.insert(it, item); mQueueNotEmptyCondition.signal(); return event->eventID(); } static bool MatchesEventID( void *cookie, const sp<TimedEventQueue::Event> &event) { TimedEventQueue::event_id *id = static_cast<TimedEventQueue::event_id *>(cookie); if (event->eventID() != *id) { return false; } bool TimedEventQueue::cancelEvent(const sp<Event> &event) { *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() && (*it).event != event) { while (it != mQueue.end()) { if (!(*predicate)(cookie, (*it).event)) { ++it; } if (it == mQueue.end()) { return false; continue; } if (it == mQueue.begin()) { mQueueHeadChangedCondition.signal(); } mQueue.erase(it); it = mQueue.erase(it); return true; if (stopAfterFirstMatch) { return; } } } // static Loading
media/libstagefright/include/TimedEventQueue.h +30 −6 Original line number Diff line number Diff line Loading @@ -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 &); }; Loading @@ -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(); Loading @@ -90,6 +113,7 @@ private: Mutex mLock; Condition mQueueNotEmptyCondition; Condition mQueueHeadChangedCondition; event_id mNextEventID; bool mRunning; bool mStopped; Loading