/*
 * Copyright (C) 2016 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.
 */
#ifndef ANDROID_HARDWARE_HIDL_CACHE_H
#define ANDROID_HARDWARE_HIDL_CACHE_H

#include <utils/Log.h>

namespace android {
namespace hardware {

// A generic cache to map Key to sp<Value>. The cache records are kept with
// wp<Value>, so that it does not block the Value to be garbage collected
// when there's no other sp<> externally.
template <class Key, class Value, class Compare = std::less<Key>>
class HidlCache : public virtual RefBase {
    using Mutex = std::mutex;
    using Lock = std::lock_guard<Mutex>;

   public:
    //  A RAII class to manage lock/unlock HidlCache.
    class HidlCacheLock : public virtual RefBase {
       public:
        HidlCacheLock(sp<HidlCache> cache, const Key& key) : mCache(cache), mKey(key) {
            mCache->lock(mKey);
        }
        ~HidlCacheLock() { mCache->unlock(mKey); }

       private:
        sp<HidlCache> mCache;
        const Key mKey;
    };
    // lock the IMemory refered by key and keep it alive even if there's no
    // other memory block refers to.
    virtual bool lock(const Key& key);
    virtual sp<Value> unlock(const Key& key);
    virtual bool flush(const Key& key);
    // fetch the sp<Value> with key from cache,
    // make a new instance with fill() if it does not present currently.
    virtual sp<Value> fetch(const Key& key);
    virtual sp<HidlCacheLock> lockGuard(const Key& key) { return new HidlCacheLock(this, key); }

    virtual ~HidlCache() {}

   protected:
    friend void HidlCacheWhiteBoxTest();
    // This method shall be called with a lock held
    virtual sp<Value> fillLocked(const Key& key) = 0;

    // @return nullptr if it does not present currently.
    // @note This method shall be called with a lock held
    virtual sp<Value> getCachedLocked(const Key& key);
    bool cached(Key key) const { return mCached.count(key) > 0; }
    bool locked(Key key) const { return mLocked.count(key) > 0; }
    Mutex mMutex;

    std::map<Key, wp<Value>, Compare> mCached;
    std::map<Key, sp<Value>, Compare> mLocked;
};

template <class Key, class Value, class Compare>
bool HidlCache<Key, Value, Compare>::lock(const Key& key) {
    {
        Lock lock(mMutex);
        if (cached(key)) {
            sp<Value> im = mCached[key].promote();
            if (im != nullptr) {
                mLocked[key] = im;
                return true;
            } else {
                mCached.erase(key);
            }
        }
    }
    sp<Value> value = fetch(key);
    if (value == nullptr) {
        return false;
    } else {
        Lock lock(mMutex);
        mLocked[key] = value;
        return true;
    }
}

template <class Key, class Value, class Compare>
sp<Value> HidlCache<Key, Value, Compare>::unlock(const Key& key) {
    Lock lock(mMutex);
    if (locked(key) > 0) {
        sp<Value> v = mLocked[key];
        mLocked.erase(key);
        return v;
    }
    return nullptr;
}

template <class Key, class Value, class Compare>
bool HidlCache<Key, Value, Compare>::flush(const Key& key) {
    Lock lock(mMutex);
    bool contain = cached(key);
    mCached.erase(key);
    return contain;
}

template <class Key, class Value, class Compare>
sp<Value> HidlCache<Key, Value, Compare>::getCachedLocked(const Key& key) {
    if (cached(key)) {
        wp<Value> cache = mCached[key];
        sp<Value> mem = cache.promote();
        if (mem != nullptr) {
            return mem;
        } else {
            mCached.erase(key);
        }
    }
    return nullptr;
}

template <class Key, class Value, class Compare>
sp<Value> HidlCache<Key, Value, Compare>::fetch(const Key& key) {
    Lock lock(mMutex);
    sp<Value> value = getCachedLocked(key);

    if (value == nullptr) {
        value = fillLocked(key);
    }
    return value;
}

}  // namespace hardware
}  // namespace android
#endif
