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"
26 #include "libmemcachedprotocol/common.h"
29 const uint64_t redzone_pattern
= 0xdeadbeefcafebabe;
33 const size_t initial_pool_size
= 64;
35 cache_t
*cache_create(const char *name
, size_t bufsize
, size_t align
,
36 cache_constructor_t
*constructor
, cache_destructor_t
*destructor
) {
37 cache_t
*ret
= calloc(1, sizeof(cache_t
));
38 size_t name_length
= strlen(name
);
39 char *nm
= calloc(1, (sizeof(char) * name_length
) + 1);
40 memcpy(nm
, name
, name_length
);
41 void **ptr
= calloc(initial_pool_size
, bufsize
);
42 if (ret
== NULL
|| nm
== NULL
|| ptr
== NULL
|| pthread_mutex_init(&ret
->mutex
, NULL
) == -1) {
51 ret
->freetotal
= initial_pool_size
;
52 ret
->constructor
= constructor
;
53 ret
->destructor
= destructor
;
56 ret
->bufsize
= bufsize
+ 2 * sizeof(redzone_pattern
);
58 ret
->bufsize
= bufsize
;
66 static inline void *get_object(void *ptr
) {
75 void cache_destroy(cache_t
*cache
) {
76 while (cache
->freecurr
> 0) {
77 void *ptr
= cache
->ptr
[--cache
->freecurr
];
78 if (cache
->destructor
) {
79 cache
->destructor(get_object(ptr
), NULL
);
85 pthread_mutex_destroy(&cache
->mutex
);
88 void *cache_alloc(cache_t
*cache
) {
91 pthread_mutex_lock(&cache
->mutex
);
92 if (cache
->freecurr
> 0) {
93 ret
= cache
->ptr
[--cache
->freecurr
];
94 object
= get_object(ret
);
96 object
= ret
= malloc(cache
->bufsize
);
98 object
= get_object(ret
);
100 if (cache
->constructor
&& cache
->constructor(object
, NULL
, 0)) {
106 pthread_mutex_unlock(&cache
->mutex
);
110 /* add a simple form of buffer-check */
112 *pre
= redzone_pattern
;
114 memcpy(((char *) ret
) + cache
->bufsize
- (2 * sizeof(redzone_pattern
)), &redzone_pattern
,
115 sizeof(redzone_pattern
));
122 void cache_free(cache_t
*cache
, void *ptr
) {
123 pthread_mutex_lock(&cache
->mutex
);
126 /* validate redzone... */
127 if (memcmp(((char *) ptr
) + cache
->bufsize
- (2 * sizeof(redzone_pattern
)), &redzone_pattern
,
128 sizeof(redzone_pattern
))
133 pthread_mutex_unlock(&cache
->mutex
);
138 if (*pre
!= redzone_pattern
) {
141 pthread_mutex_unlock(&cache
->mutex
);
146 if (cache
->freecurr
< cache
->freetotal
) {
147 cache
->ptr
[cache
->freecurr
++] = ptr
;
149 /* try to enlarge free connections array */
150 size_t newtotal
= cache
->freetotal
* 2;
151 void **new_free
= realloc(cache
->ptr
, sizeof(char *) * newtotal
);
153 cache
->freetotal
= newtotal
;
154 cache
->ptr
= new_free
;
155 cache
->ptr
[cache
->freecurr
++] = ptr
;
157 if (cache
->destructor
) {
158 cache
->destructor(ptr
, NULL
);
163 pthread_mutex_unlock(&cache
->mutex
);