/*
 * 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 "rsObjectBase.h"
#include "rsContext.h"

using namespace android;
using namespace android::renderscript;

pthread_mutex_t ObjectBase::gObjectInitMutex = PTHREAD_MUTEX_INITIALIZER;

ObjectBase::ObjectBase(Context *rsc) {
    mUserRefCount = 0;
    mSysRefCount = 0;
    mRSC = rsc;
    mNext = NULL;
    mPrev = NULL;

#if RS_OBJECT_DEBUG
    mStack.update(2);
#endif

    rsAssert(rsc);
    add();
    //ALOGV("ObjectBase %p con", this);
}

ObjectBase::~ObjectBase() {
    //ALOGV("~ObjectBase %p  ref %i,%i", this, mUserRefCount, mSysRefCount);
#if RS_OBJECT_DEBUG
    mStack.dump();
#endif

    if (mPrev || mNext) {
        // While the normal practice is to call remove before we call
        // delete.  Its possible for objects without a re-use list
        // for avoiding duplication to be created on the stack.  In those
        // cases we need to remove ourself here.
        asyncLock();
        remove();
        asyncUnlock();
    }

    rsAssert(!mUserRefCount);
    rsAssert(!mSysRefCount);
}

void ObjectBase::dumpLOGV(const char *op) const {
    if (mName.size()) {
        ALOGV("%s RSobj %p, name %s, refs %i,%i  links %p,%p,%p",
             op, this, mName.string(), mUserRefCount, mSysRefCount, mNext, mPrev, mRSC);
    } else {
        ALOGV("%s RSobj %p, no-name, refs %i,%i  links %p,%p,%p",
             op, this, mUserRefCount, mSysRefCount, mNext, mPrev, mRSC);
    }
}

void ObjectBase::incUserRef() const {
    __sync_fetch_and_add(&mUserRefCount, 1);
    //ALOGV("ObjectBase %p incU ref %i, %i", this, mUserRefCount, mSysRefCount);
}

void ObjectBase::incSysRef() const {
    __sync_fetch_and_add(&mSysRefCount, 1);
    //ALOGV("ObjectBase %p incS ref %i, %i", this, mUserRefCount, mSysRefCount);
}

void ObjectBase::preDestroy() const {
}

bool ObjectBase::freeChildren() {
    return false;
}

bool ObjectBase::checkDelete(const ObjectBase *ref) {
    if (!ref) {
        return false;
    }

    asyncLock();
    // This lock protects us against the non-RS threads changing
    // the ref counts.  At this point we should be the only thread
    // working on them.
    if (ref->mUserRefCount || ref->mSysRefCount) {
        asyncUnlock();
        return false;
    }

    ref->remove();
    // At this point we can unlock because there should be no possible way
    // for another thread to reference this object.
    ref->preDestroy();
    asyncUnlock();
    delete ref;
    return true;
}

bool ObjectBase::decUserRef() const {
    rsAssert(mUserRefCount > 0);
#if RS_OBJECT_DEBUG
    //ALOGV("ObjectBase %p decU ref %i, %i", this, mUserRefCount, mSysRefCount);
    if (mUserRefCount <= 0) {
        mStack.dump();
    }
#endif


    if ((__sync_fetch_and_sub(&mUserRefCount, 1) <= 1)) {
        __sync_synchronize();
        if (mSysRefCount <= 0) {
            return checkDelete(this);
        }
    }
    return false;
}

bool ObjectBase::zeroUserRef() const {
    //ALOGV("ObjectBase %p zeroU ref %i, %i", this, mUserRefCount, mSysRefCount);
    __sync_and_and_fetch(&mUserRefCount, 0);
    if ((__sync_fetch_and_sub(&mUserRefCount, 1) <= 1)) {
        __sync_synchronize();
        if (mSysRefCount <= 0) {
            return checkDelete(this);
        }
    }
    return false;
}

bool ObjectBase::decSysRef() const {
    //ALOGV("ObjectBase %p decS ref %i, %i", this, mUserRefCount, mSysRefCount);
    rsAssert(mSysRefCount > 0);
    if ((__sync_fetch_and_sub(&mSysRefCount, 1) <= 1)) {
        __sync_synchronize();
        if (mUserRefCount <= 0) {
            return checkDelete(this);
        }
    }
    return false;
}

void ObjectBase::setName(const char *name) {
    mName.setTo(name);
}

void ObjectBase::setName(const char *name, uint32_t len) {
    mName.setTo(name, len);
}

void ObjectBase::asyncLock() {
    pthread_mutex_lock(&gObjectInitMutex);
}

void ObjectBase::asyncUnlock() {
    pthread_mutex_unlock(&gObjectInitMutex);
}

void ObjectBase::add() const {
    asyncLock();

    rsAssert(!mNext);
    rsAssert(!mPrev);
    //ALOGV("calling add  rsc %p", mRSC);
    mNext = mRSC->mObjHead;
    if (mRSC->mObjHead) {
        mRSC->mObjHead->mPrev = this;
    }
    mRSC->mObjHead = this;

    asyncUnlock();
}

void ObjectBase::remove() const {
    //ALOGV("calling remove  rsc %p", mRSC);
    if (!mRSC) {
        rsAssert(!mPrev);
        rsAssert(!mNext);
        return;
    }

    if (mRSC->mObjHead == this) {
        mRSC->mObjHead = mNext;
    }
    if (mPrev) {
        mPrev->mNext = mNext;
    }
    if (mNext) {
        mNext->mPrev = mPrev;
    }
    mPrev = NULL;
    mNext = NULL;
}

void ObjectBase::zeroAllUserRef(Context *rsc) {
    if (rsc->props.mLogObjects) {
        ALOGV("Forcing release of all outstanding user refs.");
    }

    // This operation can be slow, only to be called during context cleanup.
    const ObjectBase * o = rsc->mObjHead;
    while (o) {
        //ALOGE("o %p", o);
        if (o->zeroUserRef()) {
            // deleted the object and possibly others, restart from head.
            o = rsc->mObjHead;
            //ALOGE("o head %p", o);
        } else {
            o = o->mNext;
            //ALOGE("o next %p", o);
        }
    }

    if (rsc->props.mLogObjects) {
        ALOGV("Objects remaining.");
        dumpAll(rsc);
    }
}

void ObjectBase::freeAllChildren(Context *rsc) {
    if (rsc->props.mLogObjects) {
        ALOGV("Forcing release of all child objects.");
    }

    // This operation can be slow, only to be called during context cleanup.
    ObjectBase * o = (ObjectBase *)rsc->mObjHead;
    while (o) {
        if (o->freeChildren()) {
            // deleted ref to self and possibly others, restart from head.
            o = (ObjectBase *)rsc->mObjHead;
        } else {
            o = (ObjectBase *)o->mNext;
        }
    }

    if (rsc->props.mLogObjects) {
        ALOGV("Objects remaining.");
        dumpAll(rsc);
    }
}

void ObjectBase::dumpAll(Context *rsc) {
    asyncLock();

    ALOGV("Dumping all objects");
    const ObjectBase * o = rsc->mObjHead;
    while (o) {
        ALOGV(" Object %p", o);
        o->dumpLOGV("  ");
        o = o->mNext;
    }

    asyncUnlock();
}

bool ObjectBase::isValid(const Context *rsc, const ObjectBase *obj) {
    asyncLock();

    const ObjectBase * o = rsc->mObjHead;
    while (o) {
        if (o == obj) {
            asyncUnlock();
            return true;
        }
        o = o->mNext;
    }
    asyncUnlock();
    return false;
}

