Add object cache to the revision pool.
[libgit2.git] / src / revobject.c
blobc6736542ff91f0d0c6b6a8ecf08eccd70f202cbb
1 /*
2 * This file is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2,
4 * as published by the Free Software Foundation.
6 * In addition to the permissions in the GNU General Public License,
7 * the authors give you unlimited permission to link the compiled
8 * version of this file into combinations with other programs,
9 * and to distribute those combinations without any restriction
10 * coming from the use of this file. (The General Public License
11 * restrictions do apply in other respects; for example, they cover
12 * modification of the file, and distribution when not linked into
13 * a combined executable.)
15 * This file is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; see the file COPYING. If not, write to
22 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
26 #include "common.h"
27 #include "revobject.h"
29 const float max_load_factor = 0.65;
31 unsigned int git_revpool_table__hash(const git_oid *id)
33 const unsigned int m = 0x5bd1e995;
34 const int r = 24;
36 unsigned int h = 0xA8A3D5;
37 int i;
39 for (i = 0; i < GIT_OID_RAWSZ / 4; ++i)
41 unsigned int k = ((unsigned int *)id->id)[i];
43 k *= m;
44 k ^= k >> r;
45 k *= m;
46 h *= m;
47 h ^= k;
50 h ^= h >> 13;
51 h *= m;
52 h ^= h >> 15;
54 return h;
57 git_revpool_table *git_revpool_table_create(unsigned int min_size)
59 git_revpool_table *table;
60 int i;
62 table = git__malloc(sizeof(table));
64 if (table == NULL)
65 return NULL;
67 // round up size to closest power of 2
68 min_size--;
69 min_size |= min_size >> 1;
70 min_size |= min_size >> 2;
71 min_size |= min_size >> 4;
72 min_size |= min_size >> 8;
73 min_size |= min_size >> 16;
75 table->size_mask = min_size;
76 table->count = 0;
77 table->max_count = (min_size + 1) * max_load_factor;
79 table->nodes = git__malloc((min_size + 1) * sizeof(git_revpool_node *));
81 if (table->nodes == NULL)
83 free(table);
84 return NULL;
87 for (i = 0; i <= min_size; ++i)
88 table->nodes[i] = NULL;
90 return table;
93 int git_revpool_table_insert(git_revpool_table *table, git_revpool_object *object)
95 git_revpool_node *node;
96 unsigned int index, hash;
98 if (table == NULL)
99 return -1;
101 if (table->count + 1 > table->max_count)
102 git_revpool_table_resize(table);
104 node = git__malloc(sizeof(git_revpool_node));
105 if (node == NULL)
106 return -1;
108 hash = git_revpool_table__hash(&object->id);
109 index = (hash & table->size_mask);
111 node->object = object;
112 node->hash = hash;
113 node->next = table->nodes[index];
115 table->nodes[index] = node;
116 table->count++;
118 return 0;
121 git_revpool_object *git_revpool_table_lookup(git_revpool_table *table, const git_oid *id)
123 git_revpool_node *node;
124 unsigned int index, hash;
126 if (table == NULL)
127 return NULL;
129 hash = git_revpool_table__hash(id);
130 index = (hash & table->size_mask);
131 node = table->nodes[index];
133 while (node != NULL)
135 if (node->hash == hash && git_oid_cmp(id, &node->object->id) == 0)
136 return node->object;
138 node = node->next;
141 return NULL;
144 void git_revpool_table_resize(git_revpool_table *table)
146 git_revpool_node **new_nodes;
147 unsigned int new_size, i;
149 new_size = (table->size_mask + 1) * 2;
151 new_nodes = git__malloc(new_size * sizeof(git_revpool_node *));
152 if (new_nodes == NULL)
153 return;
155 memset(new_nodes, 0x0, new_size * sizeof(git_revpool_node *));
157 for (i = 0; i <= table->size_mask; ++i)
159 git_revpool_node *n;
160 unsigned int index;
162 while ((n = table->nodes[i]) != NULL)
164 table->nodes[i] = n->next;
165 index = n->hash & (new_size - 1);
166 n->next = new_nodes[index];
167 new_nodes[index] = n;
171 free(table->nodes);
172 table->nodes = new_nodes;
173 table->size_mask = (new_size - 1);
174 table->max_count = new_size * max_load_factor;
178 void git_revpool_table_free(git_revpool_table *table)