Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0df9dca authored by Sergio Giro's avatar Sergio Giro Committed by Gerrit Code Review
Browse files

Merge "libutils: fix cache removal when callback invalidates the key"

parents 8f8a88ca b7170fe3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -200,11 +200,11 @@ bool LruCache<TKey, TValue>::remove(const TKey& key) {
        return false;
    }
    Entry* entry = *find_result;
    mSet->erase(entry);
    if (mListener) {
        (*mListener)(entry->key, entry->value);
    }
    detachFromCache(*entry);
    mSet->erase(entry);
    delete entry;
    return true;
}
+38 −0
Original line number Diff line number Diff line
@@ -73,6 +73,13 @@ struct ComplexValue {

ssize_t ComplexValue::instanceCount = 0;

struct KeyWithPointer {
    int *ptr;
    bool operator ==(const KeyWithPointer& other) const {
        return *ptr == *other.ptr;
    }
};

} // namespace


@@ -84,6 +91,10 @@ template<> inline android::hash_t hash_type(const ComplexKey& value) {
    return hash_type(value.k);
}

template<> inline android::hash_t hash_type(const KeyWithPointer& value) {
    return hash_type(*value.ptr);
}

class EntryRemovedCallback : public OnEntryRemoved<SimpleKey, StringValue> {
public:
    EntryRemovedCallback() : callbackCount(0), lastKey(-1), lastValue(NULL) { }
@@ -98,6 +109,14 @@ public:
    StringValue lastValue;
};

class InvalidateKeyCallback : public OnEntryRemoved<KeyWithPointer, StringValue> {
public:
    void operator()(KeyWithPointer& k, StringValue&) {
        delete k.ptr;
        k.ptr = nullptr;
    }
};

class LruCacheTest : public testing::Test {
protected:
    virtual void SetUp() {
@@ -293,6 +312,25 @@ TEST_F(LruCacheTest, CallbackOnClear) {
    EXPECT_EQ(3, callback.callbackCount);
}

TEST_F(LruCacheTest, CallbackRemovesKeyWorksOK) {
    LruCache<KeyWithPointer, StringValue> cache(1);
    InvalidateKeyCallback callback;
    cache.setOnEntryRemovedListener(&callback);
    KeyWithPointer key1;
    key1.ptr = new int(1);
    KeyWithPointer key2;
    key2.ptr = new int(2);

    cache.put(key1, "one");
    // As the size of the cache is 1, the put will call the callback.
    // Make sure everything goes smoothly even if the callback invalidates
    // the key (b/24785286)
    cache.put(key2, "two");
    EXPECT_EQ(1U, cache.size());
    EXPECT_STREQ("two", cache.get(key2));
    cache.clear();
}

TEST_F(LruCacheTest, IteratorCheck) {
    LruCache<int, int> cache(100);