/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkCachedData.h"
#include "SkDiscardableMemory.h"

//#define TRACK_CACHEDDATA_LIFETIME

#ifdef TRACK_CACHEDDATA_LIFETIME
static int32_t gCachedDataCounter;

static void inc() {
    int32_t oldCount = sk_atomic_inc(&gCachedDataCounter);
    SkDebugf("SkCachedData inc %d\n", oldCount + 1);
}

static void dec() {
    int32_t oldCount = sk_atomic_dec(&gCachedDataCounter);
    SkDebugf("SkCachedData dec %d\n", oldCount - 1);
}
#else
static void inc() {}
static void dec() {}
#endif

SkCachedData::SkCachedData(void* data, size_t size)
    : fData(data)
    , fSize(size)
    , fRefCnt(1)
    , fStorageType(kMalloc_StorageType)
    , fInCache(false)
    , fIsLocked(true)
{
    fStorage.fMalloc = data;
    inc();
}

SkCachedData::SkCachedData(size_t size, SkDiscardableMemory* dm)
    : fData(dm->data())
    , fSize(size)
    , fRefCnt(1)
    , fStorageType(kDiscardableMemory_StorageType)
    , fInCache(false)
    , fIsLocked(true)
{
    fStorage.fDM = dm;
    inc();
}

SkCachedData::~SkCachedData() {
    switch (fStorageType) {
        case kMalloc_StorageType:
            sk_free(fStorage.fMalloc);
            break;
        case kDiscardableMemory_StorageType:
            delete fStorage.fDM;
            break;
    }
    dec();
}

class SkCachedData::AutoMutexWritable {
public:
    AutoMutexWritable(const SkCachedData* cd) : fCD(const_cast<SkCachedData*>(cd)) {
        fCD->fMutex.acquire();
        fCD->validate();
    }
    ~AutoMutexWritable() {
        fCD->validate();
        fCD->fMutex.release();
    }

    SkCachedData* get() { return fCD; }
    SkCachedData* operator->() { return fCD; }

private:
    SkCachedData* fCD;
};

void SkCachedData::internalRef(bool fromCache) const {
    AutoMutexWritable(this)->inMutexRef(fromCache);
}

void SkCachedData::internalUnref(bool fromCache) const {
    if (AutoMutexWritable(this)->inMutexUnref(fromCache)) {
        // can't delete inside doInternalUnref, since it is locking a mutex (which we own)
        delete this;
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////

void SkCachedData::inMutexRef(bool fromCache) {
    if ((1 == fRefCnt) && fInCache) {
        this->inMutexLock();
    }

    fRefCnt += 1;
    if (fromCache) {
        SkASSERT(!fInCache);
        fInCache = true;
    }
}

bool SkCachedData::inMutexUnref(bool fromCache) {
    switch (--fRefCnt) {
        case 0:
            // we're going to be deleted, so we need to be unlocked (for DiscardableMemory)
            if (fIsLocked) {
                this->inMutexUnlock();
            }
            break;
        case 1:
            if (fInCache && !fromCache) {
                // If we're down to 1 owner, and that owner is the cache, this it is safe
                // to unlock (and mutate fData) even if the cache is in a different thread,
                // as the cache is NOT allowed to inspect or use fData.
                this->inMutexUnlock();
            }
            break;
        default:
            break;
    }

    if (fromCache) {
        SkASSERT(fInCache);
        fInCache = false;
    }

    // return true when we need to be deleted
    return 0 == fRefCnt;
}

void SkCachedData::inMutexLock() {
    fMutex.assertHeld();

    SkASSERT(!fIsLocked);
    fIsLocked = true;

    switch (fStorageType) {
        case kMalloc_StorageType:
            this->setData(fStorage.fMalloc);
            break;
        case kDiscardableMemory_StorageType:
            if (fStorage.fDM->lock()) {
                void* ptr = fStorage.fDM->data();
                SkASSERT(ptr);
                this->setData(ptr);
            } else {
                this->setData(nullptr);   // signal failure to lock, contents are gone
            }
            break;
    }
}

void SkCachedData::inMutexUnlock() {
    fMutex.assertHeld();

    SkASSERT(fIsLocked);
    fIsLocked = false;

    switch (fStorageType) {
        case kMalloc_StorageType:
            // nothing to do/check
            break;
        case kDiscardableMemory_StorageType:
            if (fData) {    // did the previous lock succeed?
                fStorage.fDM->unlock();
            }
            break;
    }
    this->setData(nullptr);   // signal that we're in an unlocked state
}

///////////////////////////////////////////////////////////////////////////////////////////////////

#ifdef SK_DEBUG
void SkCachedData::validate() const {
    if (fIsLocked) {
        SkASSERT((fInCache && fRefCnt > 1) || !fInCache);
        switch (fStorageType) {
            case kMalloc_StorageType:
                SkASSERT(fData == fStorage.fMalloc);
                break;
            case kDiscardableMemory_StorageType:
                // fData can be null or the actual value, depending if DM's lock succeeded
                break;
        }
    } else {
        SkASSERT((fInCache && 1 == fRefCnt) || (0 == fRefCnt));
        SkASSERT(nullptr == fData);
    }
}
#endif
