summaryrefslogtreecommitdiff
path: root/lib/lvgl/src/misc/cache/lv_cache.c
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-06-12 17:54:40 +1000
committerjacqueline <me@jacqueline.id.au>2024-06-12 17:54:40 +1000
commit64bd9053a25297f7a442ca831c7da5b44bd33f84 (patch)
treea90c6cad25a12028302ab1a5334510fba0229bae /lib/lvgl/src/misc/cache/lv_cache.c
parent611176ed667c4ed7ee9f609e958f9404f4aee91d (diff)
downloadtangara-fw-64bd9053a25297f7a442ca831c7da5b44bd33f84.tar.gz
Update LVGL to v9.1.0
Diffstat (limited to 'lib/lvgl/src/misc/cache/lv_cache.c')
-rw-r--r--lib/lvgl/src/misc/cache/lv_cache.c275
1 files changed, 275 insertions, 0 deletions
diff --git a/lib/lvgl/src/misc/cache/lv_cache.c b/lib/lvgl/src/misc/cache/lv_cache.c
new file mode 100644
index 00000000..e22cd9e4
--- /dev/null
+++ b/lib/lvgl/src/misc/cache/lv_cache.c
@@ -0,0 +1,275 @@
+/**
+* @file lv_cache.c
+*
+*/
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "lv_cache.h"
+#include "../../stdlib/lv_sprintf.h"
+#include "../lv_assert.h"
+#include "lv_cache_entry_private.h"
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+static void cache_drop_internal_no_lock(lv_cache_t * cache, const void * key, void * user_data);
+static bool cache_evict_one_internal_no_lock(lv_cache_t * cache, void * user_data);
+static lv_cache_entry_t * cache_add_internal_no_lock(lv_cache_t * cache, const void * key, void * user_data);
+/**********************
+ * GLOBAL VARIABLES
+ **********************/
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+
+/**********************
+ * MACROS
+ **********************/
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+
+lv_cache_t * lv_cache_create(const lv_cache_class_t * cache_class,
+ size_t node_size, size_t max_size,
+ lv_cache_ops_t ops)
+{
+ lv_cache_t * cache = cache_class->alloc_cb();
+ LV_ASSERT_MALLOC(cache);
+
+ cache->clz = cache_class;
+ cache->node_size = node_size;
+ cache->max_size = max_size;
+ cache->size = 0;
+ cache->ops = ops;
+
+ if(cache->clz->init_cb(cache) == false) {
+ LV_LOG_ERROR("Cache init failed");
+ lv_free(cache);
+ return NULL;
+ }
+
+ lv_mutex_init(&cache->lock);
+
+ return cache;
+}
+
+void lv_cache_destroy(lv_cache_t * cache, void * user_data)
+{
+ LV_ASSERT_NULL(cache);
+
+ lv_mutex_lock(&cache->lock);
+ cache->clz->destroy_cb(cache, user_data);
+ lv_mutex_unlock(&cache->lock);
+ lv_mutex_delete(&cache->lock);
+ lv_free(cache);
+}
+
+lv_cache_entry_t * lv_cache_acquire(lv_cache_t * cache, const void * key, void * user_data)
+{
+ LV_ASSERT_NULL(cache);
+ LV_ASSERT_NULL(key);
+
+ lv_mutex_lock(&cache->lock);
+ lv_cache_entry_t * entry = cache->clz->get_cb(cache, key, user_data);
+ if(entry != NULL) {
+ lv_cache_entry_acquire_data(entry);
+ }
+ lv_mutex_unlock(&cache->lock);
+ return entry;
+}
+void lv_cache_release(lv_cache_t * cache, lv_cache_entry_t * entry, void * user_data)
+{
+ LV_ASSERT_NULL(entry);
+
+ lv_mutex_lock(&cache->lock);
+ lv_cache_entry_release_data(entry, user_data);
+
+ if(lv_cache_entry_get_ref(entry) == 0 && lv_cache_entry_is_invalid(entry)) {
+ cache->ops.free_cb(lv_cache_entry_get_data(entry), user_data);
+ lv_cache_entry_delete(entry);
+ }
+ lv_mutex_unlock(&cache->lock);
+}
+lv_cache_entry_t * lv_cache_add(lv_cache_t * cache, const void * key, void * user_data)
+{
+ LV_ASSERT_NULL(cache);
+ LV_ASSERT_NULL(key);
+
+ lv_mutex_lock(&cache->lock);
+ lv_cache_entry_t * entry = cache_add_internal_no_lock(cache, key, user_data);
+ if(entry != NULL) {
+ lv_cache_entry_acquire_data(entry);
+ }
+ lv_mutex_unlock(&cache->lock);
+
+ return entry;
+}
+lv_cache_entry_t * lv_cache_acquire_or_create(lv_cache_t * cache, const void * key, void * user_data)
+{
+ LV_ASSERT_NULL(cache);
+ LV_ASSERT_NULL(key);
+
+ lv_mutex_lock(&cache->lock);
+ lv_cache_entry_t * entry = cache->clz->get_cb(cache, key, user_data);
+ if(entry != NULL) {
+ lv_cache_entry_acquire_data(entry);
+ lv_mutex_unlock(&cache->lock);
+ return entry;
+ }
+ entry = cache_add_internal_no_lock(cache, key, user_data);
+ if(entry == NULL) {
+ lv_mutex_unlock(&cache->lock);
+ return NULL;
+ }
+ bool create_res = cache->ops.create_cb(lv_cache_entry_get_data(entry), user_data);
+ if(create_res == false) {
+ cache->clz->remove_cb(cache, entry, user_data);
+ lv_cache_entry_delete(entry);
+ entry = NULL;
+ }
+ else {
+ lv_cache_entry_acquire_data(entry);
+ }
+ lv_mutex_unlock(&cache->lock);
+ return entry;
+}
+void lv_cache_reserve(lv_cache_t * cache, uint32_t reserved_size, void * user_data)
+{
+ LV_ASSERT_NULL(cache);
+
+ for(lv_cache_reserve_cond_res_t reserve_cond_res = cache->clz->reserve_cond_cb(cache, NULL, reserved_size, user_data);
+ reserve_cond_res == LV_CACHE_RESERVE_COND_NEED_VICTIM;
+ reserve_cond_res = cache->clz->reserve_cond_cb(cache, NULL, reserved_size, user_data))
+ cache_evict_one_internal_no_lock(cache, user_data);
+
+}
+void lv_cache_drop(lv_cache_t * cache, const void * key, void * user_data)
+{
+ LV_ASSERT_NULL(cache);
+ LV_ASSERT_NULL(key);
+
+ lv_mutex_lock(&cache->lock);
+ cache_drop_internal_no_lock(cache, key, user_data);
+ lv_mutex_unlock(&cache->lock);
+}
+bool lv_cache_evict_one(lv_cache_t * cache, void * user_data)
+{
+ LV_ASSERT_NULL(cache);
+
+ lv_mutex_lock(&cache->lock);
+ bool res = cache_evict_one_internal_no_lock(cache, user_data);
+ lv_mutex_unlock(&cache->lock);
+
+ return res;
+}
+void lv_cache_drop_all(lv_cache_t * cache, void * user_data)
+{
+ LV_ASSERT_NULL(cache);
+
+ lv_mutex_lock(&cache->lock);
+ cache->clz->drop_all_cb(cache, user_data);
+ lv_mutex_unlock(&cache->lock);
+}
+
+void lv_cache_set_max_size(lv_cache_t * cache, size_t max_size, void * user_data)
+{
+ LV_UNUSED(user_data);
+ cache->max_size = max_size;
+}
+size_t lv_cache_get_max_size(lv_cache_t * cache, void * user_data)
+{
+ LV_UNUSED(user_data);
+ return cache->max_size;
+}
+size_t lv_cache_get_size(lv_cache_t * cache, void * user_data)
+{
+ LV_UNUSED(user_data);
+ return cache->size;
+}
+size_t lv_cache_get_free_size(lv_cache_t * cache, void * user_data)
+{
+ LV_UNUSED(user_data);
+ return cache->max_size - cache->size;
+}
+void lv_cache_set_compare_cb(lv_cache_t * cache, lv_cache_compare_cb_t compare_cb, void * user_data)
+{
+ LV_UNUSED(user_data);
+ cache->ops.compare_cb = compare_cb;
+}
+void lv_cache_set_create_cb(lv_cache_t * cache, lv_cache_create_cb_t alloc_cb, void * user_data)
+{
+ LV_UNUSED(user_data);
+ cache->ops.create_cb = alloc_cb;
+}
+void lv_cache_set_free_cb(lv_cache_t * cache, lv_cache_free_cb_t free_cb, void * user_data)
+{
+ LV_UNUSED(user_data);
+ cache->ops.free_cb = free_cb;
+}
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+static void cache_drop_internal_no_lock(lv_cache_t * cache, const void * key, void * user_data)
+{
+ lv_cache_entry_t * entry = cache->clz->get_cb(cache, key, user_data);
+ if(entry == NULL) {
+ return;
+ }
+
+ if(lv_cache_entry_get_ref(entry) == 0) {
+ cache->clz->remove_cb(cache, entry, user_data);
+ cache->ops.free_cb(lv_cache_entry_get_data(entry), user_data);
+ lv_cache_entry_delete(entry);
+ }
+ else {
+ lv_cache_entry_set_invalid(entry, true);
+ cache->clz->remove_cb(cache, entry, user_data);
+ }
+}
+
+static bool cache_evict_one_internal_no_lock(lv_cache_t * cache, void * user_data)
+{
+ lv_cache_entry_t * victim = cache->clz->get_victim_cb(cache, user_data);
+
+ if(victim == NULL) {
+ LV_LOG_ERROR("No victim found");
+ return false;
+ }
+
+ cache->clz->remove_cb(cache, victim, user_data);
+ cache->ops.free_cb(lv_cache_entry_get_data(victim), user_data);
+ lv_cache_entry_delete(victim);
+ return true;
+}
+
+static lv_cache_entry_t * cache_add_internal_no_lock(lv_cache_t * cache, const void * key, void * user_data)
+{
+ lv_cache_reserve_cond_res_t reserve_cond_res = cache->clz->reserve_cond_cb(cache, key, 0, user_data);
+ if(reserve_cond_res == LV_CACHE_RESERVE_COND_TOO_LARGE) {
+ LV_LOG_ERROR("data %p is too large that exceeds max size (%" LV_PRIu32 ")", key, cache->max_size);
+ return NULL;
+ }
+
+ for(; reserve_cond_res == LV_CACHE_RESERVE_COND_NEED_VICTIM;
+ reserve_cond_res = cache->clz->reserve_cond_cb(cache, key, 0, user_data))
+ if(cache_evict_one_internal_no_lock(cache, user_data) == false)
+ return NULL;
+
+ lv_cache_entry_t * entry = cache->clz->add_cb(cache, key, user_data);
+
+ return entry;
+}