3
#include "apop_internal.h" //just for OMP_critical
7
#define lock omp_set_lock(&v->mutex);
8
#define unlock omp_unset_lock(&v->mutex);
21
unsigned long int hashed_name;
23
apop_vtable_elmt_s *elmts;
29
apop_vtable_s *vtable_list;
32
//The Dan J Bernstein string hashing algorithm.
33
static unsigned long apop_settings_hash(char const *str){
34
unsigned long int hash = 5381;
36
while ((c = *str++)) hash = hash*33 + c;
40
static apop_vtable_s *find_tab(unsigned long h, int *ctr){
41
apop_vtable_s *v = vtable_list;
43
for ( ; v->hashed_name; (*ctr)++, v++) if (v->hashed_name== h) break;
47
//return 0 = found; removed
48
//return 1 = not found; no-op
49
int apop_vtable_drop(char const *tabname, unsigned long hash){
50
if (!vtable_list) return 1;
51
unsigned long h = apop_settings_hash(tabname);
52
apop_vtable_s *v = find_tab(h, &ignore_me);
55
for (int i=0; i< v->elmt_ct; i++)
56
if (hash == v->elmts[i].hash) {
57
memmove(v->elmts+i, v->elmts+i+1, sizeof(apop_vtable_elmt_s)*(v->elmt_ct-i));
66
int apop_vtable_add(char const *tabname, void *fn_in, unsigned long hash){
67
if (!vtable_list){vtable_list = calloc(1, sizeof(apop_vtable_s));}
69
unsigned long h = apop_settings_hash(tabname);
74
//add a table if need be.
75
OMP_critical (new_vtable)
77
v = find_tab(h, &ctr);
80
vtable_list = realloc(vtable_list, (ctr+2)* sizeof(apop_vtable_s));
81
vtable_list[ctr] = (apop_vtable_s){.elmts=calloc(1, sizeof(apop_vtable_elmt_s))};
82
vtable_list[ctr+1] = (apop_vtable_s){ };
84
omp_init_lock(&vtable_list[ctr].mutex);
85
omp_set_lock(&vtable_list[ctr].mutex);
87
vtable_list[ctr].name = tabname;
88
vtable_list[ctr].hashed_name = h;
95
//If this hash is already present, don't re-add.
96
for (int i=0; i< v->elmt_ct; i++) if (hash == v->elmts[i].hash) {unlock; return 0;}
99
v->elmts = realloc(v->elmts, (++(v->elmt_ct))* sizeof(apop_vtable_elmt_s));
100
v->elmts[v->elmt_ct-1] = (apop_vtable_elmt_s){.hash=hash, .fn=fn_in};
105
void *apop_vtable_get(char const *tabname, unsigned long hash){
106
if (!vtable_list) return NULL;
107
unsigned long thash = apop_settings_hash(tabname);
108
apop_vtable_s *v = find_tab(thash, &ignore_me);
109
if (!v->hashed_name) return NULL;
112
for (int i=0; i< v->elmt_ct; i++)
113
if (hash == v->elmts[i].hash) {unlock; return v->elmts[i].fn;}