2 * Copyright (C) 2009-2011 the libgit2 contributors
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
9 #include "repository.h"
11 #include "thread-utils.h"
14 int git_cache_init(git_cache
*cache
, size_t size
, git_cached_obj_freeptr free_ptr
)
19 /* round up size to closest power of 2 */
28 cache
->size_mask
= size
- 1;
30 cache
->free_obj
= free_ptr
;
32 git_mutex_init(&cache
->lock
);
34 cache
->nodes
= git__malloc(size
* sizeof(git_cached_obj
*));
35 if (cache
->nodes
== NULL
)
38 memset(cache
->nodes
, 0x0, size
* sizeof(git_cached_obj
*));
42 void git_cache_free(git_cache
*cache
)
46 for (i
= 0; i
< (cache
->size_mask
+ 1); ++i
) {
47 if (cache
->nodes
[i
] != NULL
)
48 git_cached_obj_decref(cache
->nodes
[i
], cache
->free_obj
);
51 git__free(cache
->nodes
);
54 void *git_cache_get(git_cache
*cache
, const git_oid
*oid
)
57 git_cached_obj
*node
= NULL
, *result
= NULL
;
59 memcpy(&hash
, oid
->id
, sizeof(hash
));
61 git_mutex_lock(&cache
->lock
);
63 node
= cache
->nodes
[hash
& cache
->size_mask
];
65 if (node
!= NULL
&& git_oid_cmp(&node
->oid
, oid
) == 0) {
66 git_cached_obj_incref(node
);
70 git_mutex_unlock(&cache
->lock
);
75 void *git_cache_try_store(git_cache
*cache
, void *_entry
)
77 git_cached_obj
*entry
= _entry
;
80 memcpy(&hash
, &entry
->oid
, sizeof(hash
));
82 /* increase the refcount on this object, because
83 * the cache now owns it */
84 git_cached_obj_incref(entry
);
86 git_mutex_lock(&cache
->lock
);
88 git_cached_obj
*node
= cache
->nodes
[hash
& cache
->size_mask
];
91 cache
->nodes
[hash
& cache
->size_mask
] = entry
;
92 } else if (git_oid_cmp(&node
->oid
, &entry
->oid
) == 0) {
93 git_cached_obj_decref(entry
, cache
->free_obj
);
96 git_cached_obj_decref(node
, cache
->free_obj
);
97 cache
->nodes
[hash
& cache
->size_mask
] = entry
;
100 git_mutex_unlock(&cache
->lock
);
102 /* increase the refcount again, because we are
103 * returning it to the user */
104 git_cached_obj_incref(entry
);