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

#ifndef SkCachedData_DEFINED
#define SkCachedData_DEFINED

#include "SkMutex.h"
#include "SkTypes.h"

class SkDiscardableMemory;

class SkCachedData : ::SkNoncopyable {
public:
    SkCachedData(void* mallocData, size_t size);
    SkCachedData(size_t size, SkDiscardableMemory*);
    virtual ~SkCachedData();

    size_t size() const { return fSize; }
    const void* data() const { return fData; }

    void* writable_data() { return fData; }

    void ref() const { this->internalRef(false); }
    void unref() const { this->internalUnref(false); }

    int testing_only_getRefCnt() const { return fRefCnt; }
    bool testing_only_isLocked() const { return fIsLocked; }
    bool testing_only_isInCache() const { return fInCache; }

protected:
    // called when fData changes. could be NULL.
    virtual void onDataChange(void* oldData, void* newData) {}

private:
    SkMutex fMutex;     // could use a pool of these...

    enum StorageType {
        kDiscardableMemory_StorageType,
        kMalloc_StorageType
    };

    union {
        SkDiscardableMemory*    fDM;
        void*                   fMalloc;
    } fStorage;
    void*       fData;
    size_t      fSize;
    int         fRefCnt;    // low-bit means we're owned by the cache
    StorageType fStorageType;
    bool        fInCache;
    bool        fIsLocked;

    void internalRef(bool fromCache) const;
    void internalUnref(bool fromCache) const;

    void inMutexRef(bool fromCache);
    bool inMutexUnref(bool fromCache);  // returns true if we should delete "this"
    void inMutexLock();
    void inMutexUnlock();

    // called whenever our fData might change (lock or unlock)
    void setData(void* newData) {
        if (newData != fData) {
            // notify our subclasses of the change
            this->onDataChange(fData, newData);
            fData = newData;
        }
    }

    class AutoMutexWritable;

public:
#ifdef SK_DEBUG
    void validate() const;
#else
    void validate() const {}
#endif

   /*
     *  Attaching a data to to a SkResourceCache (only one at a time) enables the data to be
     *  unlocked when the cache is the only owner, thus freeing it to be purged (assuming the
     *  data is backed by a SkDiscardableMemory).
     *
     *  When attached, it also automatically attempts to "lock" the data when the first client
     *  ref's the data (typically from a find(key, visitor) call).
     *
     *  Thus the data will always be "locked" when a non-cache has a ref on it (whether or not
     *  the lock succeeded to recover the memory -- check data() to see if it is NULL).
     */

    /*
     *  Call when adding this instance to a SkResourceCache::Rec subclass
     *  (typically in the Rec's constructor).
     */
    void attachToCacheAndRef() const { this->internalRef(true); }

    /*
     *  Call when removing this instance from a SkResourceCache::Rec subclass
     *  (typically in the Rec's destructor).
     */
    void detachFromCacheAndUnref() const { this->internalUnref(true); }
};

#endif
