1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
13 const uint64_t redzone_pattern
= 0xdeadbeefcafebabe;
17 const size_t initial_pool_size
= 64;
19 cache_t
* cache_create(const char *name
, size_t bufsize
, size_t align
,
20 cache_constructor_t
* constructor
,
21 cache_destructor_t
* destructor
) {
22 cache_t
* ret
= calloc(1, sizeof(cache_t
));
23 char* nm
= strdup(name
);
24 void** ptr
= calloc(initial_pool_size
, bufsize
);
25 if (ret
== NULL
|| nm
== NULL
|| ptr
== NULL
||
26 pthread_mutex_init(&ret
->mutex
, NULL
) == -1) {
35 ret
->freetotal
= initial_pool_size
;
36 ret
->constructor
= constructor
;
37 ret
->destructor
= destructor
;
40 ret
->bufsize
= bufsize
+ 2 * sizeof(redzone_pattern
);
42 ret
->bufsize
= bufsize
;
50 static inline void* get_object(void *ptr
) {
59 void cache_destroy(cache_t
*cache
) {
60 while (cache
->freecurr
> 0) {
61 void *ptr
= cache
->ptr
[--cache
->freecurr
];
62 if (cache
->destructor
) {
63 cache
->destructor(get_object(ptr
), NULL
);
69 pthread_mutex_destroy(&cache
->mutex
);
72 void* cache_alloc(cache_t
*cache
) {
75 pthread_mutex_lock(&cache
->mutex
);
76 if (cache
->freecurr
> 0) {
77 ret
= cache
->ptr
[--cache
->freecurr
];
78 object
= get_object(ret
);
80 object
= ret
= malloc(cache
->bufsize
);
82 object
= get_object(ret
);
84 if (cache
->constructor
!= NULL
&&
85 cache
->constructor(object
, NULL
, 0) != 0) {
91 pthread_mutex_unlock(&cache
->mutex
);
95 /* add a simple form of buffer-check */
97 *pre
= redzone_pattern
;
99 memcpy(((char*)ret
) + cache
->bufsize
- (2 * sizeof(redzone_pattern
)),
100 &redzone_pattern
, sizeof(redzone_pattern
));
107 void cache_free(cache_t
*cache
, void *ptr
) {
108 pthread_mutex_lock(&cache
->mutex
);
111 /* validate redzone... */
112 if (memcmp(((char*)ptr
) + cache
->bufsize
- (2 * sizeof(redzone_pattern
)),
113 &redzone_pattern
, sizeof(redzone_pattern
)) != 0) {
116 pthread_mutex_unlock(&cache
->mutex
);
121 if (*pre
!= redzone_pattern
) {
124 pthread_mutex_unlock(&cache
->mutex
);
129 if (cache
->freecurr
< cache
->freetotal
) {
130 cache
->ptr
[cache
->freecurr
++] = ptr
;
132 /* try to enlarge free connections array */
133 size_t newtotal
= cache
->freetotal
* 2;
134 void **new_free
= realloc(cache
->ptr
, sizeof(char *) * newtotal
);
136 cache
->freetotal
= newtotal
;
137 cache
->ptr
= new_free
;
138 cache
->ptr
[cache
->freecurr
++] = ptr
;
140 if (cache
->destructor
) {
141 cache
->destructor(ptr
, NULL
);
147 pthread_mutex_unlock(&cache
->mutex
);