/*
 * 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
