1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
16 const uint64_t redzone_pattern
= 0xdeadbeefcafebabe;
20 const int initial_pool_size
= 64;
22 cache_t
* cache_create(const char *name
, size_t bufsize
, size_t align
,
23 cache_constructor_t
* constructor
,
24 cache_destructor_t
* destructor
) {
25 cache_t
* ret
= calloc(1, sizeof(cache_t
));
26 char* nm
= strdup(name
);
27 void** ptr
= calloc(initial_pool_size
, sizeof(void*));
28 if (ret
== NULL
|| nm
== NULL
|| ptr
== NULL
||
29 pthread_mutex_init(&ret
->mutex
, NULL
) == -1) {
38 ret
->freetotal
= initial_pool_size
;
39 ret
->constructor
= constructor
;
40 ret
->destructor
= destructor
;
43 ret
->bufsize
= bufsize
+ 2 * sizeof(redzone_pattern
);
45 ret
->bufsize
= bufsize
;
51 static inline void* get_object(void *ptr
) {
60 void cache_destroy(cache_t
*cache
) {
61 while (cache
->freecurr
> 0) {
62 void *ptr
= cache
->ptr
[--cache
->freecurr
];
63 if (cache
->destructor
) {
64 cache
->destructor(get_object(ptr
), NULL
);
70 pthread_mutex_destroy(&cache
->mutex
);
73 void* cache_alloc(cache_t
*cache
) {
76 pthread_mutex_lock(&cache
->mutex
);
77 if (cache
->freecurr
> 0) {
78 ret
= cache
->ptr
[--cache
->freecurr
];
79 object
= get_object(ret
);
81 object
= ret
= malloc(cache
->bufsize
);
83 object
= get_object(ret
);
85 if (cache
->constructor
!= NULL
&&
86 cache
->constructor(object
, NULL
, 0) != 0) {
92 pthread_mutex_unlock(&cache
->mutex
);
96 /* add a simple form of buffer-check */
98 *pre
= redzone_pattern
;
100 memcpy(((char*)ret
) + cache
->bufsize
- (2 * sizeof(redzone_pattern
)),
101 &redzone_pattern
, sizeof(redzone_pattern
));
108 void cache_free(cache_t
*cache
, void *ptr
) {
109 pthread_mutex_lock(&cache
->mutex
);
112 /* validate redzone... */
113 if (memcmp(((char*)ptr
) + cache
->bufsize
- (2 * sizeof(redzone_pattern
)),
114 &redzone_pattern
, sizeof(redzone_pattern
)) != 0) {
117 pthread_mutex_unlock(&cache
->mutex
);
122 if (*pre
!= redzone_pattern
) {
125 pthread_mutex_unlock(&cache
->mutex
);
130 if (cache
->freecurr
< cache
->freetotal
) {
131 cache
->ptr
[cache
->freecurr
++] = ptr
;
133 /* try to enlarge free connections array */
134 size_t newtotal
= cache
->freetotal
* 2;
135 void **new_free
= realloc(cache
->ptr
, sizeof(char *) * newtotal
);
137 cache
->freetotal
= newtotal
;
138 cache
->ptr
= new_free
;
139 cache
->ptr
[cache
->freecurr
++] = ptr
;
141 if (cache
->destructor
) {
142 cache
->destructor(ptr
, NULL
);
148 pthread_mutex_unlock(&cache
->mutex
);