From 6ead5d9f140529edfb744584fa5427b84b4dc13a Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 20 Apr 2009 19:39:12 -0700 Subject: a brand new MessageQueue for SurfaceFlinger. --- libs/surfaceflinger/MessageQueue.cpp | 161 +++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 libs/surfaceflinger/MessageQueue.cpp (limited to 'libs/surfaceflinger/MessageQueue.cpp') diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp new file mode 100644 index 000000000000..907938300ff1 --- /dev/null +++ b/libs/surfaceflinger/MessageQueue.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "MessageQueue.h" + +namespace android { + +// --------------------------------------------------------------------------- + +MessageQueue::MessageQueue() +{ + mInvalidateMessage = new MessageBase(INVALIDATE); +} + +MessageQueue::~MessageQueue() +{ +} + +MessageList::NODE_PTR MessageQueue::waitMessage(nsecs_t timeout) +{ + MessageList::NODE_PTR result; + bool again; + do { + const nsecs_t timeoutTime = systemTime() + timeout; + while (true) { + Mutex::Autolock _l(mLock); + nsecs_t now = systemTime(); + nsecs_t nextEventTime = -1; + + // invalidate messages are always handled first + if (mInvalidate) { + mInvalidate = false; + mInvalidateMessage->when = now; + result = mInvalidateMessage; + break; + } + + result = mMessages.head(); + + if (result != 0) { + if (result->when <= now) { + // there is a message to deliver + mMessages.remove(result); + result->detach(); + break; + } + if (timeout>=0 && timeoutTime < now) { + // we timed-out, return a NULL message + result = 0; + break; + } + nextEventTime = result->when; + result = 0; + } + + if (timeout >= 0 && nextEventTime > 0) { + if (nextEventTime > timeoutTime) { + nextEventTime = timeoutTime; + } + } + + if (nextEventTime >= 0) { + //LOGD("nextEventTime = %lld ms", nextEventTime); + if (nextEventTime > 0) { + // we're about to wait, flush the binder command buffer + IPCThreadState::self()->flushCommands(); + mCondition.wait(mLock, nextEventTime); + } + } else { + //LOGD("going to wait"); + // we're about to wait, flush the binder command buffer + IPCThreadState::self()->flushCommands(); + mCondition.wait(mLock); + } + } + // here we're not holding the lock anymore + + if (result == 0) + break; + + again = result->handler(); + if (again) { + // the message has been processed. release our reference to it + // without holding the lock. + result = 0; + } + + } while (again); + return result; +} + +status_t MessageQueue::postMessage( + const MessageList::NODE_PTR& message, nsecs_t relTime, uint32_t flags) +{ + return queueMessage(message, relTime, flags); +} + +status_t MessageQueue::invalidate() { + Mutex::Autolock _l(mLock); + mInvalidate = true; + mCondition.signal(); + return NO_ERROR; +} + +status_t MessageQueue::queueMessage( + const MessageList::NODE_PTR& message, nsecs_t relTime, uint32_t flags) +{ + Mutex::Autolock _l(mLock); + message->when = systemTime() + relTime; + mMessages.insert(message); + + //LOGD("MessageQueue::queueMessage time = %lld ms", message->when); + //dumpLocked(message); + + mCondition.signal(); + return NO_ERROR; +} + +void MessageQueue::dump(const MessageList::NODE_PTR& message) +{ + Mutex::Autolock _l(mLock); + dumpLocked(message); +} + +void MessageQueue::dumpLocked(const MessageList::NODE_PTR& message) +{ + MessageList::NODE_PTR l(mMessages.head()); + int c = 0; + while (l != 0) { + const char tick = (l == message) ? '>' : ' '; + LOGD("%c %d: msg{.what=%08x, when=%lld}", tick, c, l->what, l->when); + l = l->getNext(); + c++; + } +} + +// --------------------------------------------------------------------------- + +}; // namespace android -- cgit v1.2.3-59-g8ed1b From bdbe6024a543bd740b0c194db9c12e4150c55c59 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 28 Apr 2009 03:17:50 -0700 Subject: make use of the perfectly fine List.h instead of our own reimplementation of a linked list. --- libs/surfaceflinger/MessageQueue.cpp | 57 ++++++++++---- libs/surfaceflinger/MessageQueue.h | 140 +++++---------------------------- libs/surfaceflinger/SurfaceFlinger.cpp | 2 +- 3 files changed, 64 insertions(+), 135 deletions(-) (limited to 'libs/surfaceflinger/MessageQueue.cpp') diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp index 907938300ff1..52d4db806388 100644 --- a/libs/surfaceflinger/MessageQueue.cpp +++ b/libs/surfaceflinger/MessageQueue.cpp @@ -29,6 +29,27 @@ namespace android { // --------------------------------------------------------------------------- +void MessageList::insert(const sp& node) +{ + LIST::iterator cur(mList.begin()); + LIST::iterator end(mList.end()); + while (cur != end) { + if (*node < **cur) { + mList.insert(cur, node); + return; + } + ++cur; + } + mList.insert(++end, node); +} + +void MessageList::remove(MessageList::LIST::iterator pos) +{ + mList.erase(pos); +} + +// --------------------------------------------------------------------------- + MessageQueue::MessageQueue() { mInvalidateMessage = new MessageBase(INVALIDATE); @@ -38,9 +59,10 @@ MessageQueue::~MessageQueue() { } -MessageList::NODE_PTR MessageQueue::waitMessage(nsecs_t timeout) +MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout) { - MessageList::NODE_PTR result; + MessageList::value_type result; + bool again; do { const nsecs_t timeoutTime = systemTime() + timeout; @@ -57,13 +79,15 @@ MessageList::NODE_PTR MessageQueue::waitMessage(nsecs_t timeout) break; } - result = mMessages.head(); - + LIST::iterator cur(mMessages.begin()); + if (cur != mMessages.end()) { + result = *cur; + } + if (result != 0) { if (result->when <= now) { // there is a message to deliver - mMessages.remove(result); - result->detach(); + mMessages.remove(cur); break; } if (timeout>=0 && timeoutTime < now) { @@ -108,11 +132,12 @@ MessageList::NODE_PTR MessageQueue::waitMessage(nsecs_t timeout) } } while (again); + return result; } status_t MessageQueue::postMessage( - const MessageList::NODE_PTR& message, nsecs_t relTime, uint32_t flags) + const MessageList::value_type& message, nsecs_t relTime, uint32_t flags) { return queueMessage(message, relTime, flags); } @@ -125,7 +150,7 @@ status_t MessageQueue::invalidate() { } status_t MessageQueue::queueMessage( - const MessageList::NODE_PTR& message, nsecs_t relTime, uint32_t flags) + const MessageList::value_type& message, nsecs_t relTime, uint32_t flags) { Mutex::Autolock _l(mLock); message->when = systemTime() + relTime; @@ -138,20 +163,22 @@ status_t MessageQueue::queueMessage( return NO_ERROR; } -void MessageQueue::dump(const MessageList::NODE_PTR& message) +void MessageQueue::dump(const MessageList::value_type& message) { Mutex::Autolock _l(mLock); dumpLocked(message); } -void MessageQueue::dumpLocked(const MessageList::NODE_PTR& message) +void MessageQueue::dumpLocked(const MessageList::value_type& message) { - MessageList::NODE_PTR l(mMessages.head()); + LIST::const_iterator cur(mMessages.begin()); + LIST::const_iterator end(mMessages.end()); int c = 0; - while (l != 0) { - const char tick = (l == message) ? '>' : ' '; - LOGD("%c %d: msg{.what=%08x, when=%lld}", tick, c, l->what, l->when); - l = l->getNext(); + while (cur != end) { + const char tick = (*cur == message) ? '>' : ' '; + LOGD("%c %d: msg{.what=%08x, when=%lld}", + tick, c, (*cur)->what, (*cur)->when); + ++cur; c++; } } diff --git a/libs/surfaceflinger/MessageQueue.h b/libs/surfaceflinger/MessageQueue.h index c118897dd699..dc8138d1667d 100644 --- a/libs/surfaceflinger/MessageQueue.h +++ b/libs/surfaceflinger/MessageQueue.h @@ -23,125 +23,34 @@ #include #include +#include namespace android { // --------------------------------------------------------------------------- -template -class DoublyLinkedList -{ -protected: - typedef NODE_PTR_TYPE NODE_PTR; - - NODE_PTR mFirst; - NODE_PTR mLast; - -public: - class Node { - friend class DoublyLinkedList; - mutable NODE_PTR next; - mutable NODE_PTR prev; - public: - typedef NODE_PTR PTR; - inline NODE_PTR getNext() const { return next; } - inline NODE_PTR getPrev() const { return prev; } - void detach() { - prev = 0; - next = 0; - } - }; - - DoublyLinkedList() : mFirst(0), mLast(0) { } - ~DoublyLinkedList() { } - - bool isEmpty() const { return mFirst == 0; } - const NODE_PTR& head() const { return mFirst; } - const NODE_PTR& tail() const { return mLast; } - const NODE_PTR& head() { return mFirst; } - const NODE_PTR& tail() { return mLast; } - - void insertAfter(const NODE_PTR& node, const NODE_PTR& newNode) { - newNode->prev = node; - newNode->next = node->next; - if (node->next == 0) mLast = newNode; - else node->next->prev = newNode; - node->next = newNode; - } - - void insertBefore(const NODE_PTR& node, const NODE_PTR& newNode) { - newNode->prev = node->prev; - newNode->next = node; - if (node->prev == 0) mFirst = newNode; - else node->prev->next = newNode; - node->prev = newNode; - } - - void insertHead(const NODE_PTR& newNode) { - if (mFirst == 0) { - mFirst = mLast = newNode; - newNode->prev = newNode->next = 0; - } else { - newNode->prev = 0; - newNode->next = mFirst; - mFirst->prev = newNode; - mFirst = newNode; - } - } - - void insertTail(const NODE_PTR& newNode) { - if (mLast == 0) { - insertHead(newNode); - } else { - newNode->prev = mLast; - newNode->next = 0; - mLast->next = newNode; - mLast = newNode; - } - } - - NODE_PTR remove(const NODE_PTR& node) { - if (node->prev == 0) mFirst = node->next; - else node->prev->next = node->next; - if (node->next == 0) mLast = node->prev; - else node->next->prev = node->prev; - return node; - } -}; +class MessageBase; -// --------------------------------------------------------------------------- - -template -class SortedList : protected DoublyLinkedList< NODE_PTR_TYPE > +class MessageList { - typedef DoublyLinkedList< NODE_PTR_TYPE > forward; + List< sp > mList; + typedef List< sp > LIST; public: - typedef NODE_PTR_TYPE NODE_PTR; - inline bool isEmpty() const { return forward::isEmpty(); } - inline const NODE_PTR& head() const { return forward::head(); } - inline const NODE_PTR& tail() const { return forward::tail(); } - inline const NODE_PTR& head() { return forward::head(); } - inline const NODE_PTR& tail() { return forward::tail(); } - inline NODE_PTR remove(const NODE_PTR& node) { return forward::remove(node); } - void insert(const NODE_PTR& node) { - NODE_PTR l(head()); - while (l != 0) { - if (*node < *l) { - insertBefore(l, node); - return; - } - l = l->getNext(); - } - insertTail(node); - } + typedef sp value_type; + inline LIST::iterator begin() { return mList.begin(); } + inline LIST::const_iterator begin() const { return mList.begin(); } + inline LIST::iterator end() { return mList.end(); } + inline LIST::const_iterator end() const { return mList.end(); } + inline bool isEmpty() const { return mList.empty(); } + void insert(const sp& node); + void remove(LIST::iterator pos); }; // ============================================================================ class MessageBase : - public LightRefBase, - public DoublyLinkedList< sp >::Node + public LightRefBase { public: nsecs_t when; @@ -168,16 +77,9 @@ inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) { // --------------------------------------------------------------------------- -/* - * MessageList is a sorted list of sp - */ - -typedef SortedList< MessageBase::Node::PTR > MessageList; - -// --------------------------------------------------------------------------- - class MessageQueue { + typedef List< sp > LIST; public: // this is a work-around the multichar constant warning. A macro would @@ -197,25 +99,25 @@ public: INVALIDATE = WHAT<'_','p','d','t'>::Value }; - MessageList::NODE_PTR waitMessage(nsecs_t timeout = -1); + MessageList::value_type waitMessage(nsecs_t timeout = -1); - status_t postMessage(const MessageList::NODE_PTR& message, + status_t postMessage(const MessageList::value_type& message, nsecs_t reltime=0, uint32_t flags = 0); status_t invalidate(); - void dump(const MessageList::NODE_PTR& message); + void dump(const MessageList::value_type& message); private: - status_t queueMessage(const MessageList::NODE_PTR& message, + status_t queueMessage(const MessageList::value_type& message, nsecs_t reltime, uint32_t flags); - void dumpLocked(const MessageList::NODE_PTR& message); + void dumpLocked(const MessageList::value_type& message); Mutex mLock; Condition mCondition; MessageList mMessages; bool mInvalidate; - MessageList::NODE_PTR mInvalidateMessage; + MessageList::value_type mInvalidateMessage; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index be91cddfdd09..6b421588e19c 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -429,7 +429,7 @@ void SurfaceFlinger::waitForEvent() timeout = waitTime>0 ? waitTime : 0; } - MessageList::NODE_PTR msg = mEventQueue.waitMessage(timeout); + MessageList::value_type msg = mEventQueue.waitMessage(timeout); if (msg != 0) { mFreezeDisplayTime = 0; switch (msg->what) { -- cgit v1.2.3-59-g8ed1b