diff --git a/test-app/runtime/src/main/cpp/JEnv.h b/test-app/runtime/src/main/cpp/JEnv.h index 9c809449a..fa33bc5d0 100644 --- a/test-app/runtime/src/main/cpp/JEnv.h +++ b/test-app/runtime/src/main/cpp/JEnv.h @@ -20,6 +20,10 @@ class JEnv { jsize GetArrayLength(jarray array); + inline bool isSameObject(jobject obj1, jobject obj2) { + return m_env->IsSameObject(obj1, obj2) == JNI_TRUE; + } + jmethodID GetMethodID(jclass clazz, const std::string& name, const std::string& sig); jmethodID GetStaticMethodID(jclass clazz, const std::string& name, const std::string& sig); std::pair GetInterfaceStaticMethodIDAndJClass( diff --git a/test-app/runtime/src/main/cpp/LRUCache.h b/test-app/runtime/src/main/cpp/LRUCache.h index c3318ff6d..d2e4c95d0 100644 --- a/test-app/runtime/src/main/cpp/LRUCache.h +++ b/test-app/runtime/src/main/cpp/LRUCache.h @@ -19,7 +19,7 @@ #include #include -#include +#include "robin_hood.h" namespace tns { // Class providing fixed-size (by number of records) @@ -41,12 +41,12 @@ class LRUCache { typedef std::list key_tracker_type; // Key to value and key history iterator - typedef std::unordered_map< key_type, std::pair > key_to_value_type; + typedef robin_hood::unordered_map< key_type, std::pair > key_to_value_type; - // Constuctor specifies the cached function and + // Constructor specifies the cached function and // the maximum number of records to be stored - LRUCache(value_type (*loadCallback)(const key_type&, void*), void (*evictCallback)(const value_type&, void*), size_t capacity, void* state) - : m_loadCallback(loadCallback), m_capacity(capacity), m_evictCallback(evictCallback), m_state(state) { + LRUCache(value_type (*loadCallback)(const key_type&, void*), void (*evictCallback)(const value_type&, void*), bool (*cacheValidCallback)(const key_type&, const value_type&, void*), size_t capacity, void* state) + : m_loadCallback(loadCallback), m_capacity(capacity), m_evictCallback(evictCallback), m_cacheValidCallback(cacheValidCallback), m_state(state) { assert(m_loadCallback != nullptr); assert((0 < m_capacity) && (m_capacity < 10000)); } @@ -57,6 +57,15 @@ class LRUCache { // Attempt to find existing record auto it = m_key_to_value.find(k); + if (m_cacheValidCallback != nullptr && it != m_key_to_value.end()) { + //check if cache is still valid + if (!m_cacheValidCallback(k, (*it).second.first, m_state)) { + //cache is not valid anymore, evict the key + evictKey(k); + it = m_key_to_value.end(); + } + } + if (it == m_key_to_value.end()) { // We don't have it: @@ -98,6 +107,17 @@ class LRUCache { private: + void evictKey(const key_type& key) { + auto it = m_key_to_value.find(key); + if (it != m_key_to_value.end()) { + if (m_evictCallback != nullptr) { + m_evictCallback((*it).second.first, m_state); + } + m_key_tracker.erase((*it).second.second); + m_key_to_value.erase(it); + } + } + // Record a fresh key-value pair in the cache void insert(const key_type& k, const value_type& v) { // Method is only called on cache misses @@ -113,7 +133,7 @@ class LRUCache { // Create the key-value entry, // linked to the usage record. - m_key_to_value.insert(std::make_pair(k, std::make_pair(v, it))); + m_key_to_value.emplace(k, std::make_pair(v, it)); // No need to check return, // given previous assert. } @@ -141,6 +161,8 @@ class LRUCache { void (*m_evictCallback)(const value_type&, void*); + bool (*m_cacheValidCallback)(const key_type&, const value_type&, void*); + // Maximum number of key-value pairs to be retained const size_t m_capacity; diff --git a/test-app/runtime/src/main/cpp/ObjectManager.cpp b/test-app/runtime/src/main/cpp/ObjectManager.cpp index 7e1901fdf..ba01fb8b6 100644 --- a/test-app/runtime/src/main/cpp/ObjectManager.cpp +++ b/test-app/runtime/src/main/cpp/ObjectManager.cpp @@ -20,7 +20,7 @@ ObjectManager::ObjectManager(jobject javaRuntimeObject) : m_javaRuntimeObject(javaRuntimeObject), m_numberOfGC(0), m_currentObjectId(0), - m_cache(NewWeakGlobalRefCallback, DeleteWeakGlobalRefCallback, 1000, this) { + m_cache(NewWeakGlobalRefCallback, DeleteWeakGlobalRefCallback, ValidateWeakGlobalRefCallback, 1000, this) { JEnv env; auto runtimeClass = env.FindClass("com/tns/Runtime"); @@ -507,12 +507,15 @@ jweak ObjectManager::NewWeakGlobalRefCallback(const int &javaObjectID, void *sta } void ObjectManager::DeleteWeakGlobalRefCallback(const jweak &object, void *state) { - auto objManager = reinterpret_cast(state); - JEnv env; env.DeleteWeakGlobalRef(object); } +bool ObjectManager::ValidateWeakGlobalRefCallback(const int &javaObjectID, const jweak &object, void *state) { + JEnv env; + return !env.isSameObject(object, NULL); +} + Local ObjectManager::GetEmptyObject(Isolate *isolate) { auto emptyObjCtorFunc = Local::New(isolate, *m_poJsWrapperFunc); auto context = Runtime::GetRuntime(isolate)->GetContext(); diff --git a/test-app/runtime/src/main/cpp/ObjectManager.h b/test-app/runtime/src/main/cpp/ObjectManager.h index 28cfd4372..a0ae80703 100644 --- a/test-app/runtime/src/main/cpp/ObjectManager.h +++ b/test-app/runtime/src/main/cpp/ObjectManager.h @@ -179,6 +179,8 @@ class ObjectManager { static void DeleteWeakGlobalRefCallback(const jweak& object, void* state); + static bool ValidateWeakGlobalRefCallback(const int &javaObjectID, const jweak &object, void *state); + static void JSWrapperConstructorCallback(const v8::FunctionCallbackInfo& info); jobject m_javaRuntimeObject;