diff options
Diffstat (limited to 'samples/C/cache.c')
| -rw-r--r-- | samples/C/cache.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/samples/C/cache.c b/samples/C/cache.c new file mode 100644 index 0000000..f8d8940 --- /dev/null +++ b/samples/C/cache.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "common.h" +#include "repository.h" +#include "commit.h" +#include "thread-utils.h" +#include "util.h" +#include "cache.h" + +int git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr) +{ + if (size < 8) + size = 8; + size = git__size_t_powerof2(size); + + cache->size_mask = size - 1; + cache->lru_count = 0; + cache->free_obj = free_ptr; + + git_mutex_init(&cache->lock); + + cache->nodes = git__malloc(size * sizeof(git_cached_obj *)); + GITERR_CHECK_ALLOC(cache->nodes); + + memset(cache->nodes, 0x0, size * sizeof(git_cached_obj *)); + return 0; +} + +void git_cache_free(git_cache *cache) +{ + size_t i; + + for (i = 0; i < (cache->size_mask + 1); ++i) { + if (cache->nodes[i] != NULL) + git_cached_obj_decref(cache->nodes[i], cache->free_obj); + } + + git__free(cache->nodes); +} + +void *git_cache_get(git_cache *cache, const git_oid *oid) +{ + uint32_t hash; + git_cached_obj *node = NULL, *result = NULL; + + memcpy(&hash, oid->id, sizeof(hash)); + + git_mutex_lock(&cache->lock); + { + node = cache->nodes[hash & cache->size_mask]; + + if (node != NULL && git_oid_cmp(&node->oid, oid) == 0) { + git_cached_obj_incref(node); + result = node; + } + } + git_mutex_unlock(&cache->lock); + + return result; +} + +void *git_cache_try_store(git_cache *cache, void *_entry) +{ + git_cached_obj *entry = _entry; + uint32_t hash; + + memcpy(&hash, &entry->oid, sizeof(uint32_t)); + + /* increase the refcount on this object, because + * the cache now owns it */ + git_cached_obj_incref(entry); + + git_mutex_lock(&cache->lock); + { + git_cached_obj *node = cache->nodes[hash & cache->size_mask]; + + if (node == NULL) { + cache->nodes[hash & cache->size_mask] = entry; + } else if (git_oid_cmp(&node->oid, &entry->oid) == 0) { + git_cached_obj_decref(entry, cache->free_obj); + entry = node; + } else { + git_cached_obj_decref(node, cache->free_obj); + cache->nodes[hash & cache->size_mask] = entry; + } + } + git_mutex_unlock(&cache->lock); + + /* increase the refcount again, because we are + * returning it to the user */ + git_cached_obj_incref(entry); + + return entry; +} |
