2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
16 #include "mem_config.h"
22 #include "libmemcachedprotocol/common.h"
29 const uint64_t redzone_pattern
= 0xdeadbeefcafebabe;
34 const size_t initial_pool_size
= 64;
36 cache_t
*cache_create(const char *name
, size_t bufsize
, size_t align
,
37 cache_constructor_t
*constructor
, cache_destructor_t
*destructor
) {
38 cache_t
*ret
= calloc(1, sizeof(cache_t
));
39 size_t name_length
= strlen(name
);
40 char *nm
= calloc(1, (sizeof(char) * name_length
) + 1);
41 memcpy(nm
, name
, name_length
);
42 void **ptr
= calloc(initial_pool_size
, bufsize
);
43 if (ret
== NULL
|| nm
== NULL
|| ptr
== NULL
|| pthread_mutex_init(&ret
->mutex
, NULL
) == -1) {
52 ret
->freetotal
= initial_pool_size
;
53 ret
->constructor
= constructor
;
54 ret
->destructor
= destructor
;
57 ret
->bufsize
= bufsize
+ 2 * sizeof(redzone_pattern
);
59 ret
->bufsize
= bufsize
;
67 static inline void *get_object(void *ptr
) {
76 void cache_destroy(cache_t
*cache
) {
77 while (cache
->freecurr
> 0) {
78 void *ptr
= cache
->ptr
[--cache
->freecurr
];
79 if (cache
->destructor
) {
80 cache
->destructor(get_object(ptr
), NULL
);
86 pthread_mutex_destroy(&cache
->mutex
);
89 void *cache_alloc(cache_t
*cache
) {
92 pthread_mutex_lock(&cache
->mutex
);
93 if (cache
->freecurr
> 0) {
94 ret
= cache
->ptr
[--cache
->freecurr
];
95 object
= get_object(ret
);
97 object
= ret
= malloc(cache
->bufsize
);
99 object
= get_object(ret
);
101 if (cache
->constructor
&& cache
->constructor(object
, NULL
, 0)) {
107 pthread_mutex_unlock(&cache
->mutex
);
111 /* add a simple form of buffer-check */
113 *pre
= redzone_pattern
;
115 memcpy(((char *) ret
) + cache
->bufsize
- (2 * sizeof(redzone_pattern
)), &redzone_pattern
,
116 sizeof(redzone_pattern
));
123 void cache_free(cache_t
*cache
, void *ptr
) {
124 pthread_mutex_lock(&cache
->mutex
);
127 /* validate redzone... */
128 if (memcmp(((char *) ptr
) + cache
->bufsize
- (2 * sizeof(redzone_pattern
)), &redzone_pattern
,
129 sizeof(redzone_pattern
))
134 pthread_mutex_unlock(&cache
->mutex
);
139 if (*pre
!= redzone_pattern
) {
142 pthread_mutex_unlock(&cache
->mutex
);
147 if (cache
->freecurr
< cache
->freetotal
) {
148 cache
->ptr
[cache
->freecurr
++] = ptr
;
150 /* try to enlarge free connections array */
151 size_t newtotal
= cache
->freetotal
* 2;
152 void **new_free
= realloc(cache
->ptr
, sizeof(char *) * newtotal
);
154 cache
->freetotal
= newtotal
;
155 cache
->ptr
= new_free
;
156 cache
->ptr
[cache
->freecurr
++] = ptr
;
158 if (cache
->destructor
) {
159 cache
->destructor(ptr
, NULL
);
164 pthread_mutex_unlock(&cache
->mutex
);
167 #endif // HAVE_UMEM_H