~ubuntu-branches/debian/sid/apophenia/sid

« back to all changes in this revision

Viewing changes to apop_vtables.c

  • Committer: Package Import Robot
  • Author(s): Jerome Benoit
  • Date: 2014-09-11 12:36:28 UTC
  • Revision ID: package-import@ubuntu.com-20140911123628-mhyqci1xk9tjicph
Tags: upstream-0.999b+ds1
ImportĀ upstreamĀ versionĀ 0.999b+ds1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdlib.h>
 
2
#include <string.h>
 
3
#include "apop_internal.h" //just for OMP_critical
 
4
 
 
5
#ifdef _OPENMP
 
6
#include <omp.h>
 
7
#define lock omp_set_lock(&v->mutex);
 
8
#define unlock omp_unset_lock(&v->mutex);
 
9
#else
 
10
#define lock 
 
11
#define unlock 
 
12
#endif
 
13
 
 
14
typedef struct {
 
15
    size_t hash;
 
16
    void *fn;
 
17
} apop_vtable_elmt_s;
 
18
 
 
19
typedef struct {
 
20
    char const *name;
 
21
    unsigned long int hashed_name;
 
22
    int elmt_ct;
 
23
    apop_vtable_elmt_s *elmts;
 
24
#ifdef _OPENMP
 
25
    omp_lock_t mutex;
 
26
#endif
 
27
} apop_vtable_s;
 
28
 
 
29
apop_vtable_s *vtable_list;
 
30
int ignore_me;
 
31
 
 
32
//The Dan J Bernstein string hashing algorithm.
 
33
static unsigned long apop_settings_hash(char const *str){
 
34
    unsigned long int hash = 5381;
 
35
    char c;
 
36
    while ((c = *str++)) hash = hash*33 + c;
 
37
    return hash;
 
38
}
 
39
 
 
40
static apop_vtable_s *find_tab(unsigned long h, int *ctr){
 
41
    apop_vtable_s *v = vtable_list;
 
42
    *ctr = 0;
 
43
    for ( ; v->hashed_name; (*ctr)++, v++) if (v->hashed_name== h) break;
 
44
    return v;
 
45
}
 
46
 
 
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);
 
53
 
 
54
    lock
 
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));
 
58
            v->elmt_ct--;
 
59
            unlock
 
60
            return 0;
 
61
        }
 
62
    unlock
 
63
    return 1;
 
64
}
 
65
 
 
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));}
 
68
 
 
69
    unsigned long h = apop_settings_hash(tabname);
 
70
    int ctr;
 
71
    apop_vtable_s *v;
 
72
 
 
73
 
 
74
    //add a table if need be.
 
75
    OMP_critical (new_vtable)
 
76
    {
 
77
    v = find_tab(h, &ctr);
 
78
 
 
79
    if (!v->hashed_name){
 
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){ };
 
83
        #ifdef _OPENMP
 
84
            omp_init_lock(&vtable_list[ctr].mutex);
 
85
            omp_set_lock(&vtable_list[ctr].mutex);
 
86
        #endif
 
87
        vtable_list[ctr].name = tabname;
 
88
        vtable_list[ctr].hashed_name = h;
 
89
        v = vtable_list+ctr;
 
90
        unlock
 
91
    }
 
92
    }
 
93
 
 
94
    lock
 
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;}
 
97
 
 
98
    //insert
 
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};
 
101
    unlock
 
102
    return 0;
 
103
}
 
104
 
 
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;
 
110
 
 
111
    lock
 
112
    for (int i=0; i< v->elmt_ct; i++)
 
113
        if (hash == v->elmts[i].hash) {unlock; return v->elmts[i].fn;}
 
114
    unlock
 
115
    return NULL;
 
116
}