cleanup. waitForCondition() now uses polymorphsim instead of templtes

the reason for the above change is that waitForCondition() had become
large over time, mainly to handle error cases, using inlines to
evaluate the condition doesn't buys us much anymore while it increases
code size.

Change-Id: I2595d850832628954b900ab8bb1796c863447bc7
This commit is contained in:
Mathias Agopian 2010-04-27 16:41:19 -07:00
parent 0a8cd0689a
commit b296533607
4 changed files with 94 additions and 93 deletions

View File

@ -176,60 +176,21 @@ protected:
SharedBufferStack& stack;
inline ConditionBase(SharedBufferBase* sbc)
: stack(*sbc->mSharedStack) { }
virtual ~ConditionBase() { };
virtual bool operator()() const = 0;
virtual const char* name() const = 0;
};
status_t waitForCondition(const ConditionBase& condition);
struct UpdateBase {
SharedBufferStack& stack;
inline UpdateBase(SharedBufferBase* sbb)
: stack(*sbb->mSharedStack) { }
};
template <typename T>
status_t waitForCondition(T condition);
template <typename T>
status_t updateCondition(T update);
};
template <typename T>
status_t SharedBufferBase::waitForCondition(T condition)
{
const SharedBufferStack& stack( *mSharedStack );
SharedClient& client( *mSharedClient );
const nsecs_t TIMEOUT = s2ns(1);
Mutex::Autolock _l(client.lock);
while ((condition()==false) &&
(stack.identity == mIdentity) &&
(stack.status == NO_ERROR))
{
status_t err = client.cv.waitRelative(client.lock, TIMEOUT);
// handle errors and timeouts
if (CC_UNLIKELY(err != NO_ERROR)) {
if (err == TIMED_OUT) {
if (condition()) {
LOGE("waitForCondition(%s) timed out (identity=%d), "
"but condition is true! We recovered but it "
"shouldn't happen." , T::name(),
stack.identity);
break;
} else {
LOGW("waitForCondition(%s) timed out "
"(identity=%d, status=%d). "
"CPU may be pegged. trying again.", T::name(),
stack.identity, stack.status);
}
} else {
LOGE("waitForCondition(%s) error (%s) ",
T::name(), strerror(-err));
return err;
}
}
}
return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status;
}
template <typename T>
status_t SharedBufferBase::updateCondition(T update) {
SharedClient& client( *mSharedClient );
@ -275,15 +236,15 @@ private:
struct DequeueCondition : public ConditionBase {
inline DequeueCondition(SharedBufferClient* sbc);
inline bool operator()();
static inline const char* name() { return "DequeueCondition"; }
inline bool operator()() const;
inline const char* name() const { return "DequeueCondition"; }
};
struct LockCondition : public ConditionBase {
int buf;
inline LockCondition(SharedBufferClient* sbc, int buf);
inline bool operator()();
static inline const char* name() { return "LockCondition"; }
inline bool operator()() const;
inline const char* name() const { return "LockCondition"; }
};
int32_t tail;
@ -334,8 +295,8 @@ private:
struct ReallocateCondition : public ConditionBase {
int buf;
inline ReallocateCondition(SharedBufferBase* sbb, int buf);
inline bool operator()();
static inline const char* name() { return "ReallocateCondition"; }
inline bool operator()() const;
inline const char* name() const { return "ReallocateCondition"; }
};
};

View File

@ -165,38 +165,36 @@ public:
// setSwapRectangle() is intended to be used by GL ES clients
void setSwapRectangle(const Rect& r);
private:
// can't be copied
Surface& operator = (Surface& rhs);
Surface(const Surface& rhs);
Surface(const sp<SurfaceControl>& control);
void init();
~Surface();
friend class SurfaceComposerClient;
friend class SurfaceControl;
/*
* Android frameworks friends
* (eventually this should go away and be replaced by proper APIs)
*/
// camera and camcorder need access to the ISurface binder interface for preview
friend class Camera;
friend class MediaRecorder;
// mediaplayer needs access to ISurface for display
// MediaPlayer needs access to ISurface for display
friend class MediaPlayer;
friend class IOMX;
// this is just to be able to write some unit tests
friend class Test;
sp<SurfaceComposerClient> getClient() const;
sp<ISurface> getISurface() const;
private:
friend class SurfaceComposerClient;
friend class SurfaceControl;
status_t getBufferLocked(int index, int usage);
// can't be copied
Surface& operator = (Surface& rhs);
Surface(const Surface& rhs);
status_t validate() const;
Surface(const sp<SurfaceControl>& control);
~Surface();
inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
/*
* android_native_window_t hooks
*/
static int setSwapInterval(android_native_window_t* window, int interval);
static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer);
static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
@ -210,8 +208,6 @@ private:
int query(int what, int* value);
int perform(int operation, va_list args);
status_t dequeueBuffer(sp<GraphicBuffer>* buffer);
void dispatch_setUsage(va_list args);
int dispatch_connect(va_list args);
int dispatch_disconnect(va_list args);
@ -222,6 +218,20 @@ private:
int disconnect(int api);
int crop(Rect const* rect);
/*
* private stuff...
*/
void init();
status_t validate() const;
sp<SurfaceComposerClient> getClient() const;
sp<ISurface> getISurface() const;
inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
status_t getBufferLocked(int index, int usage);
int getBufferIndex(const sp<GraphicBuffer>& buffer) const;
uint32_t getUsage() const;
int getConnectedApi() const;

View File

@ -195,6 +195,42 @@ int32_t SharedBufferBase::computeTail() const
return (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers;
}
status_t SharedBufferBase::waitForCondition(const ConditionBase& condition)
{
const SharedBufferStack& stack( *mSharedStack );
SharedClient& client( *mSharedClient );
const nsecs_t TIMEOUT = s2ns(1);
const int identity = mIdentity;
Mutex::Autolock _l(client.lock);
while ((condition()==false) &&
(stack.identity == identity) &&
(stack.status == NO_ERROR))
{
status_t err = client.cv.waitRelative(client.lock, TIMEOUT);
// handle errors and timeouts
if (CC_UNLIKELY(err != NO_ERROR)) {
if (err == TIMED_OUT) {
if (condition()) {
LOGE("waitForCondition(%s) timed out (identity=%d), "
"but condition is true! We recovered but it "
"shouldn't happen." , condition.name(), stack.identity);
break;
} else {
LOGW("waitForCondition(%s) timed out "
"(identity=%d, status=%d). "
"CPU may be pegged. trying again.", condition.name(),
stack.identity, stack.status);
}
} else {
LOGE("waitForCondition(%s) error (%s) ",
condition.name(), strerror(-err));
return err;
}
}
}
return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status;
}
// ============================================================================
// conditions and updates
// ============================================================================
@ -202,14 +238,14 @@ int32_t SharedBufferBase::computeTail() const
SharedBufferClient::DequeueCondition::DequeueCondition(
SharedBufferClient* sbc) : ConditionBase(sbc) {
}
bool SharedBufferClient::DequeueCondition::operator()() {
bool SharedBufferClient::DequeueCondition::operator()() const {
return stack.available > 0;
}
SharedBufferClient::LockCondition::LockCondition(
SharedBufferClient* sbc, int buf) : ConditionBase(sbc), buf(buf) {
}
bool SharedBufferClient::LockCondition::operator()() {
bool SharedBufferClient::LockCondition::operator()() const {
return (buf != stack.head ||
(stack.queued > 0 && stack.inUse != buf));
}
@ -217,7 +253,7 @@ bool SharedBufferClient::LockCondition::operator()() {
SharedBufferServer::ReallocateCondition::ReallocateCondition(
SharedBufferBase* sbb, int buf) : ConditionBase(sbb), buf(buf) {
}
bool SharedBufferServer::ReallocateCondition::operator()() {
bool SharedBufferServer::ReallocateCondition::operator()() const {
// TODO: we should also check that buf has been dequeued
return (buf != stack.head);
}

View File

@ -463,18 +463,6 @@ int Surface::perform(android_native_window_t* window,
// ----------------------------------------------------------------------------
status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer) {
android_native_buffer_t* out;
status_t err = dequeueBuffer(&out);
if (err == NO_ERROR) {
*buffer = GraphicBuffer::getSelf(out);
}
return err;
}
// ----------------------------------------------------------------------------
int Surface::dequeueBuffer(android_native_buffer_t** buffer)
{
sp<SurfaceComposerClient> client(getClient());
@ -530,7 +518,7 @@ int Surface::lockBuffer(android_native_buffer_t* buffer)
if (err != NO_ERROR)
return err;
int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex();
int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
err = mSharedBufferClient->lock(bufIdx);
LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err));
return err;
@ -547,7 +535,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
mDirtyRegion.set(mSwapRectangle);
}
int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex();
int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
mSharedBufferClient->setCrop(bufIdx, mNextBufferCrop);
mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion);
err = mSharedBufferClient->queue(bufIdx);
@ -722,13 +710,14 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
// we're intending to do software rendering from this point
setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
sp<GraphicBuffer> backBuffer;
status_t err = dequeueBuffer(&backBuffer);
android_native_buffer_t* out;
status_t err = dequeueBuffer(&out);
LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
if (err == NO_ERROR) {
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
err = lockBuffer(backBuffer.get());
LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)",
backBuffer->getIndex(), strerror(-err));
getBufferIndex(backBuffer), strerror(-err));
if (err == NO_ERROR) {
const Rect bounds(backBuffer->width, backBuffer->height);
const Region boundsRegion(bounds);
@ -797,7 +786,7 @@ status_t Surface::unlockAndPost()
err = queueBuffer(mLockedBuffer.get());
LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)",
mLockedBuffer->getIndex(), strerror(-err));
getBufferIndex(mLockedBuffer), strerror(-err));
mPostedBuffer = mLockedBuffer;
mLockedBuffer = 0;
@ -809,6 +798,11 @@ void Surface::setSwapRectangle(const Rect& r) {
mSwapRectangle = r;
}
int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const
{
return buffer->getIndex();
}
status_t Surface::getBufferLocked(int index, int usage)
{
sp<ISurface> s(mSurface);