rewrite SF's message loop on top of Looper
Change-Id: Ib56139f87a5c0b124e34da5c8151207219b2577b
This commit is contained in:
parent
26f68d62eb
commit
f61c57fe2e
|
@ -29,169 +29,81 @@ namespace android {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void MessageList::insert(const sp<MessageBase>& 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);
|
||||
MessageBase::MessageBase()
|
||||
: MessageHandler() {
|
||||
}
|
||||
|
||||
void MessageList::remove(MessageList::LIST::iterator pos)
|
||||
{
|
||||
mList.erase(pos);
|
||||
MessageBase::~MessageBase() {
|
||||
}
|
||||
|
||||
void MessageBase::handleMessage(const Message&) {
|
||||
this->handler();
|
||||
barrier.open();
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
MessageQueue::MessageQueue()
|
||||
: mInvalidate(false)
|
||||
{
|
||||
mInvalidateMessage = new MessageBase(INVALIDATE);
|
||||
}
|
||||
|
||||
MessageQueue::~MessageQueue()
|
||||
: mLooper(new Looper(true)),
|
||||
mInvalidatePending(0)
|
||||
{
|
||||
}
|
||||
|
||||
sp<MessageBase> MessageQueue::waitMessage(nsecs_t timeout)
|
||||
{
|
||||
sp<MessageBase> result;
|
||||
MessageQueue::~MessageQueue() {
|
||||
}
|
||||
|
||||
bool again;
|
||||
void MessageQueue::waitMessage() {
|
||||
do {
|
||||
const nsecs_t timeoutTime = systemTime() + timeout;
|
||||
while (true) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
nsecs_t now = systemTime();
|
||||
nsecs_t nextEventTime = -1;
|
||||
|
||||
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(cur);
|
||||
break;
|
||||
}
|
||||
nextEventTime = result->when;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
// see if we have an invalidate message
|
||||
if (mInvalidate) {
|
||||
mInvalidate = false;
|
||||
mInvalidateMessage->when = now;
|
||||
result = mInvalidateMessage;
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout >= 0) {
|
||||
if (timeoutTime < now) {
|
||||
// we timed-out, return a NULL message
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
if (nextEventTime > 0) {
|
||||
if (nextEventTime > timeoutTime) {
|
||||
nextEventTime = timeoutTime;
|
||||
}
|
||||
} else {
|
||||
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();
|
||||
const nsecs_t reltime = nextEventTime - systemTime();
|
||||
if (reltime > 0) {
|
||||
mCondition.waitRelative(mLock, reltime);
|
||||
}
|
||||
}
|
||||
} 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)
|
||||
// handle invalidate events first
|
||||
if (android_atomic_and(0, &mInvalidatePending) != 0)
|
||||
break;
|
||||
|
||||
again = result->handler();
|
||||
if (again) {
|
||||
// the message has been processed. release our reference to it
|
||||
// without holding the lock.
|
||||
result->notify();
|
||||
result = 0;
|
||||
}
|
||||
|
||||
} while (again);
|
||||
IPCThreadState::self()->flushCommands();
|
||||
|
||||
return result;
|
||||
int32_t ret = mLooper->pollOnce(-1);
|
||||
switch (ret) {
|
||||
case ALOOPER_POLL_WAKE:
|
||||
// we got woken-up there is work to do in the main loop
|
||||
continue;
|
||||
|
||||
case ALOOPER_POLL_CALLBACK:
|
||||
// callback was handled, loop again
|
||||
continue;
|
||||
|
||||
case ALOOPER_POLL_TIMEOUT:
|
||||
// timeout (should not happen)
|
||||
continue;
|
||||
|
||||
case ALOOPER_POLL_ERROR:
|
||||
LOGE("ALOOPER_POLL_ERROR");
|
||||
continue;
|
||||
|
||||
default:
|
||||
// should not happen
|
||||
LOGE("Looper::pollOnce() returned unknown status %d", ret);
|
||||
continue;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
status_t MessageQueue::postMessage(
|
||||
const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags)
|
||||
const sp<MessageBase>& messageHandler, nsecs_t relTime)
|
||||
{
|
||||
return queueMessage(message, relTime, flags);
|
||||
const Message dummyMessage;
|
||||
if (relTime > 0) {
|
||||
mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage);
|
||||
} else {
|
||||
mLooper->sendMessage(messageHandler, dummyMessage);
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t MessageQueue::invalidate() {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mInvalidate = true;
|
||||
mCondition.signal();
|
||||
android_atomic_or(1, &mInvalidatePending);
|
||||
mLooper->wake();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t MessageQueue::queueMessage(
|
||||
const sp<MessageBase>& 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 sp<MessageBase>& message)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
dumpLocked(message);
|
||||
}
|
||||
|
||||
void MessageQueue::dumpLocked(const sp<MessageBase>& message)
|
||||
{
|
||||
LIST::const_iterator cur(mMessages.begin());
|
||||
LIST::const_iterator end(mMessages.end());
|
||||
int c = 0;
|
||||
while (cur != end) {
|
||||
const char tick = (*cur == message) ? '>' : ' ';
|
||||
LOGD("%c %d: msg{.what=%08x, when=%lld}",
|
||||
tick, c, (*cur)->what, (*cur)->when);
|
||||
++cur;
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
}; // namespace android
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include <utils/threads.h>
|
||||
#include <utils/Timers.h>
|
||||
#include <utils/List.h>
|
||||
#include <utils/Looper.h>
|
||||
|
||||
#include "Barrier.h"
|
||||
|
||||
|
@ -31,92 +31,39 @@ namespace android {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class MessageBase;
|
||||
|
||||
class MessageList
|
||||
{
|
||||
List< sp<MessageBase> > mList;
|
||||
typedef List< sp<MessageBase> > LIST;
|
||||
public:
|
||||
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<MessageBase>& node);
|
||||
void remove(LIST::iterator pos);
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
||||
class MessageBase :
|
||||
public LightRefBase<MessageBase>
|
||||
class MessageBase : public MessageHandler
|
||||
{
|
||||
public:
|
||||
nsecs_t when;
|
||||
uint32_t what;
|
||||
int32_t arg0;
|
||||
|
||||
MessageBase() : when(0), what(0), arg0(0) { }
|
||||
MessageBase(uint32_t what, int32_t arg0=0)
|
||||
: when(0), what(what), arg0(arg0) { }
|
||||
MessageBase();
|
||||
|
||||
// return true if message has a handler
|
||||
virtual bool handler() { return false; }
|
||||
virtual bool handler() = 0;
|
||||
|
||||
// waits for the handler to be processed
|
||||
void wait() const { barrier.wait(); }
|
||||
|
||||
// releases all waiters. this is done automatically if
|
||||
// handler returns true
|
||||
void notify() const { barrier.open(); }
|
||||
|
||||
protected:
|
||||
virtual ~MessageBase() { }
|
||||
virtual ~MessageBase();
|
||||
|
||||
private:
|
||||
mutable Barrier barrier;
|
||||
friend class LightRefBase<MessageBase>;
|
||||
};
|
||||
virtual void handleMessage(const Message& message);
|
||||
|
||||
inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) {
|
||||
return lhs.when < rhs.when;
|
||||
}
|
||||
mutable Barrier barrier;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class MessageQueue
|
||||
{
|
||||
typedef List< sp<MessageBase> > LIST;
|
||||
public:
|
||||
class MessageQueue {
|
||||
sp<Looper> mLooper;
|
||||
volatile int32_t mInvalidatePending;
|
||||
|
||||
public:
|
||||
MessageQueue();
|
||||
~MessageQueue();
|
||||
|
||||
// pre-defined messages
|
||||
enum {
|
||||
INVALIDATE = '_upd'
|
||||
};
|
||||
|
||||
sp<MessageBase> waitMessage(nsecs_t timeout = -1);
|
||||
|
||||
status_t postMessage(const sp<MessageBase>& message,
|
||||
nsecs_t reltime=0, uint32_t flags = 0);
|
||||
|
||||
void waitMessage();
|
||||
status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
|
||||
status_t invalidate();
|
||||
|
||||
void dump(const sp<MessageBase>& message);
|
||||
|
||||
private:
|
||||
status_t queueMessage(const sp<MessageBase>& message,
|
||||
nsecs_t reltime, uint32_t flags);
|
||||
void dumpLocked(const sp<MessageBase>& message);
|
||||
|
||||
Mutex mLock;
|
||||
Condition mCondition;
|
||||
MessageList mMessages;
|
||||
bool mInvalidate;
|
||||
sp<MessageBase> mInvalidateMessage;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -311,19 +311,8 @@ status_t SurfaceFlinger::readyToRun()
|
|||
#pragma mark Events Handler
|
||||
#endif
|
||||
|
||||
void SurfaceFlinger::waitForEvent()
|
||||
{
|
||||
while (true) {
|
||||
nsecs_t timeout = -1;
|
||||
sp<MessageBase> msg = mEventQueue.waitMessage(timeout);
|
||||
if (msg != 0) {
|
||||
switch (msg->what) {
|
||||
case MessageQueue::INVALIDATE:
|
||||
// invalidate message, just return to the main loop
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void SurfaceFlinger::waitForEvent() {
|
||||
mEventQueue.waitMessage();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::signalEvent() {
|
||||
|
|
Loading…
Reference in New Issue