forked from memcached/memcached
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create a generic cache for objects of same size
The suffix pool could be thread-local and use the generic cache
- Loading branch information
Showing
10 changed files
with
530 additions
and
223 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <inttypes.h> | ||
|
||
#ifndef NDEBUG | ||
#include <signal.h> | ||
#endif | ||
|
||
#include "cache.h" | ||
|
||
#ifndef NDEBUG | ||
const uint64_t redzone_pattern = 0xdeadbeefcafebabe; | ||
int cache_error = 0; | ||
#endif | ||
|
||
const int initial_pool_size = 64; | ||
|
||
cache_t* cache_create(const char *name, size_t bufsize, size_t align, | ||
cache_constructor_t* constructor, | ||
cache_destructor_t* destructor) { | ||
cache_t* ret = calloc(1, sizeof(cache_t)); | ||
char* nm = strdup(name); | ||
void** ptr = calloc(initial_pool_size, bufsize); | ||
if (ret == NULL || nm == NULL || ptr == NULL || | ||
pthread_mutex_init(&ret->mutex, NULL) == -1) { | ||
free(ret); | ||
free(nm); | ||
free(ptr); | ||
return NULL; | ||
} | ||
|
||
ret->name = nm; | ||
ret->ptr = ptr; | ||
ret->freetotal = initial_pool_size; | ||
ret->constructor = constructor; | ||
ret->destructor = destructor; | ||
|
||
#ifndef NDEBUG | ||
ret->bufsize = bufsize + 2 * sizeof(redzone_pattern); | ||
#else | ||
ret->bufsize = bufsize; | ||
#endif | ||
|
||
return ret; | ||
} | ||
|
||
static inline void* get_object(void *ptr) { | ||
#ifndef NDEBUG | ||
uint64_t *pre = ptr; | ||
return pre + 1; | ||
#endif | ||
return ptr; | ||
} | ||
|
||
void cache_destroy(cache_t *cache) { | ||
while (cache->freecurr > 0) { | ||
void *ptr = cache->ptr[--cache->freecurr]; | ||
if (cache->destructor) { | ||
cache->destructor(get_object(ptr), NULL); | ||
} | ||
free(ptr); | ||
} | ||
free(cache->name); | ||
free(cache->ptr); | ||
pthread_mutex_destroy(&cache->mutex); | ||
} | ||
|
||
void* cache_alloc(cache_t *cache) { | ||
void *ret; | ||
void *object; | ||
pthread_mutex_lock(&cache->mutex); | ||
if (cache->freecurr > 0) { | ||
ret = cache->ptr[--cache->freecurr]; | ||
object = get_object(ret); | ||
} else { | ||
object = ret = malloc(cache->bufsize); | ||
if (ret != NULL) { | ||
object = get_object(ret); | ||
|
||
if (cache->constructor != NULL && | ||
cache->constructor(object, NULL, 0) != 0) { | ||
free(ret); | ||
object = NULL; | ||
} | ||
} | ||
} | ||
pthread_mutex_unlock(&cache->mutex); | ||
|
||
#ifndef NDEBUG | ||
if (object != NULL) { | ||
/* add a simple form of buffer-check */ | ||
uint64_t *pre = ret; | ||
*pre = redzone_pattern; | ||
ret = pre+1; | ||
memcpy(((char*)ret) + cache->bufsize - (2 * sizeof(redzone_pattern)), | ||
&redzone_pattern, sizeof(redzone_pattern)); | ||
} | ||
#endif | ||
|
||
return object; | ||
} | ||
|
||
void cache_free(cache_t *cache, void *ptr) { | ||
pthread_mutex_lock(&cache->mutex); | ||
|
||
#ifndef NDEBUG | ||
/* validate redzone... */ | ||
if (memcmp(((char*)ptr) + cache->bufsize - (2 * sizeof(redzone_pattern)), | ||
&redzone_pattern, sizeof(redzone_pattern)) != 0) { | ||
raise(SIGABRT); | ||
cache_error = 1; | ||
pthread_mutex_unlock(&cache->mutex); | ||
return; | ||
} | ||
uint64_t *pre = ptr; | ||
--pre; | ||
if (*pre != redzone_pattern) { | ||
raise(SIGABRT); | ||
cache_error = -1; | ||
pthread_mutex_unlock(&cache->mutex); | ||
return; | ||
} | ||
ptr = pre; | ||
#endif | ||
if (cache->freecurr < cache->freetotal) { | ||
cache->ptr[cache->freecurr++] = ptr; | ||
} else { | ||
/* try to enlarge free connections array */ | ||
size_t newtotal = cache->freetotal * 2; | ||
void **new_free = realloc(cache->ptr, sizeof(char *) * newtotal); | ||
if (new_free) { | ||
cache->freetotal = newtotal; | ||
cache->ptr = new_free; | ||
cache->ptr[cache->freecurr++] = ptr; | ||
} else { | ||
if (cache->destructor) { | ||
cache->destructor(ptr, NULL); | ||
} | ||
free(ptr); | ||
|
||
} | ||
} | ||
pthread_mutex_unlock(&cache->mutex); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||
#ifndef CACHE_H | ||
#define CACHE_H | ||
#include <pthread.h> | ||
|
||
#ifdef HAVE_UMEM_H | ||
#include <umem.h> | ||
#define cache_t umem_cache_t | ||
#define cache_alloc(a) umem_cache_alloc(a, UMEM_DEFAULT) | ||
#define cache_free(a, b) umem_cache_free(a, b) | ||
#define cache_create(a,b,c,d,e) umem_cache_create((char*)a, b, c, d, e, NULL, NULL, NULL, 0) | ||
#define cache_destroy(a) umem_cache_destroy(a); | ||
|
||
#else | ||
|
||
#ifndef NDEBUG | ||
/* may be used for debug purposes */ | ||
extern int cache_error; | ||
#endif | ||
|
||
typedef int cache_constructor_t(void *, void *, int); | ||
typedef void cache_destructor_t(void *, void *); | ||
|
||
typedef struct { | ||
pthread_mutex_t mutex; | ||
char *name; | ||
void **ptr; | ||
size_t bufsize; | ||
int freetotal; | ||
int freecurr; | ||
cache_constructor_t* constructor; | ||
cache_destructor_t* destructor; | ||
} cache_t; | ||
|
||
|
||
cache_t* cache_create(const char *name, size_t bufsize, size_t align, | ||
cache_constructor_t* constructor, | ||
cache_destructor_t* destructor); | ||
void cache_destroy(cache_t*); | ||
void* cache_alloc(cache_t*); | ||
void cache_free(cache_t*, void*); | ||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.