Add a generic "object decorator" interface, and make object refs use it
This allows you to add an arbitrary "decoration" of your choice to any object. It's a space- and time-efficient way to add information to arbitrary objects, especially if most objects probably do not have the decoration. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
committed by
Junio C Hamano
parent
402fa75eed
commit
a59b276e18
@ -1,75 +1,20 @@
|
||||
#include "cache.h"
|
||||
#include "object.h"
|
||||
#include "decorate.h"
|
||||
|
||||
int track_object_refs = 0;
|
||||
|
||||
static unsigned int refs_hash_size, nr_object_refs;
|
||||
static struct object_refs **refs_hash;
|
||||
static struct decoration ref_decorate;
|
||||
|
||||
static unsigned int hash_obj(struct object *obj, unsigned int n)
|
||||
struct object_refs *lookup_object_refs(struct object *base)
|
||||
{
|
||||
unsigned int hash = *(unsigned int *)obj->sha1;
|
||||
return hash % n;
|
||||
return lookup_decoration(&ref_decorate, base);
|
||||
}
|
||||
|
||||
static void insert_ref_hash(struct object_refs *ref, struct object_refs **hash, unsigned int size)
|
||||
static void add_object_refs(struct object *obj, struct object_refs *refs)
|
||||
{
|
||||
int j = hash_obj(ref->base, size);
|
||||
|
||||
while (hash[j]) {
|
||||
j++;
|
||||
if (j >= size)
|
||||
j = 0;
|
||||
}
|
||||
hash[j] = ref;
|
||||
}
|
||||
|
||||
static void grow_refs_hash(void)
|
||||
{
|
||||
int i;
|
||||
int new_hash_size = (refs_hash_size + 1000) * 3 / 2;
|
||||
struct object_refs **new_hash;
|
||||
|
||||
new_hash = xcalloc(new_hash_size, sizeof(struct object_refs *));
|
||||
for (i = 0; i < refs_hash_size; i++) {
|
||||
struct object_refs *ref = refs_hash[i];
|
||||
if (!ref)
|
||||
continue;
|
||||
insert_ref_hash(ref, new_hash, new_hash_size);
|
||||
}
|
||||
free(refs_hash);
|
||||
refs_hash = new_hash;
|
||||
refs_hash_size = new_hash_size;
|
||||
}
|
||||
|
||||
static void add_object_refs(struct object *obj, struct object_refs *ref)
|
||||
{
|
||||
int nr = nr_object_refs + 1;
|
||||
|
||||
if (nr > refs_hash_size * 2 / 3)
|
||||
grow_refs_hash();
|
||||
ref->base = obj;
|
||||
insert_ref_hash(ref, refs_hash, refs_hash_size);
|
||||
nr_object_refs = nr;
|
||||
}
|
||||
|
||||
struct object_refs *lookup_object_refs(struct object *obj)
|
||||
{
|
||||
struct object_refs *ref;
|
||||
int j;
|
||||
|
||||
/* nothing to lookup */
|
||||
if (!refs_hash_size)
|
||||
return NULL;
|
||||
j = hash_obj(obj, refs_hash_size);
|
||||
while ((ref = refs_hash[j]) != NULL) {
|
||||
if (ref->base == obj)
|
||||
break;
|
||||
j++;
|
||||
if (j >= refs_hash_size)
|
||||
j = 0;
|
||||
}
|
||||
return ref;
|
||||
if (add_decoration(&ref_decorate, obj, refs))
|
||||
die("object %s tried to add refs twice!", sha1_to_hex(obj->sha1));
|
||||
}
|
||||
|
||||
struct object_refs *alloc_object_refs(unsigned count)
|
||||
|
||||
Reference in New Issue
Block a user