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"
27 typedef SECURITY_ATTRIBUTES pthread_mutexattr_t
;
29 static inline int pthread_mutex_init(pthread_mutex_t
*m
, pthread_mutexattr_t
*a
) {
30 *m
= CreateMutexA(a
, FALSE
, NULL
);
33 static inline int pthread_mutex_destroy(pthread_mutex_t
*m
) {
34 return !CloseHandle(*m
);
36 static inline int pthread_mutex_lock(pthread_mutex_t
*m
) {
37 if (WaitForSingleObject(*m
, INFINITE
)) {
40 return GetLastError();
42 static inline int pthread_mutex_unlock(pthread_mutex_t
*m
) {
43 return !ReleaseMutex(*m
);
50 const uint64_t redzone_pattern
= 0xdeadbeefcafebabe;
55 const size_t initial_pool_size
= 64;
57 cache_t
*cache_create(const char *name
, size_t bufsize
, size_t align
,
58 cache_constructor_t
*constructor
, cache_destructor_t
*destructor
) {
59 cache_t
*ret
= calloc(1, sizeof(cache_t
));
60 size_t name_length
= strlen(name
);
61 char *nm
= calloc(1, (sizeof(char) * name_length
) + 1);
62 memcpy(nm
, name
, name_length
);
63 void **ptr
= calloc(initial_pool_size
, bufsize
);
64 if (ret
== NULL
|| nm
== NULL
|| ptr
== NULL
|| pthread_mutex_init(&ret
->mutex
, NULL
) == -1) {
73 ret
->freetotal
= initial_pool_size
;
74 ret
->constructor
= constructor
;
75 ret
->destructor
= destructor
;
78 ret
->bufsize
= bufsize
+ 2 * sizeof(redzone_pattern
);
80 ret
->bufsize
= bufsize
;
88 static inline void *get_object(void *ptr
) {
97 void cache_destroy(cache_t
*cache
) {
98 while (cache
->freecurr
> 0) {
99 void *ptr
= cache
->ptr
[--cache
->freecurr
];
100 if (cache
->destructor
) {
101 cache
->destructor(get_object(ptr
), NULL
);
107 pthread_mutex_destroy(&cache
->mutex
);
110 void *cache_alloc(cache_t
*cache
) {
113 pthread_mutex_lock(&cache
->mutex
);
114 if (cache
->freecurr
> 0) {
115 ret
= cache
->ptr
[--cache
->freecurr
];
116 object
= get_object(ret
);
118 object
= ret
= malloc(cache
->bufsize
);
120 object
= get_object(ret
);
122 if (cache
->constructor
&& cache
->constructor(object
, NULL
, 0)) {
128 pthread_mutex_unlock(&cache
->mutex
);
132 /* add a simple form of buffer-check */
134 *pre
= redzone_pattern
;
136 memcpy(((char *) ret
) + cache
->bufsize
- (2 * sizeof(redzone_pattern
)), &redzone_pattern
,
137 sizeof(redzone_pattern
));
144 void cache_free(cache_t
*cache
, void *ptr
) {
145 pthread_mutex_lock(&cache
->mutex
);
148 /* validate redzone... */
149 if (memcmp(((char *) ptr
) + cache
->bufsize
- (2 * sizeof(redzone_pattern
)), &redzone_pattern
,
150 sizeof(redzone_pattern
))
155 pthread_mutex_unlock(&cache
->mutex
);
160 if (*pre
!= redzone_pattern
) {
163 pthread_mutex_unlock(&cache
->mutex
);
168 if (cache
->freecurr
< cache
->freetotal
) {
169 cache
->ptr
[cache
->freecurr
++] = ptr
;
171 /* try to enlarge free connections array */
172 size_t newtotal
= cache
->freetotal
* 2;
173 void **new_free
= realloc(cache
->ptr
, sizeof(char *) * newtotal
);
175 cache
->freetotal
= newtotal
;
176 cache
->ptr
= new_free
;
177 cache
->ptr
[cache
->freecurr
++] = ptr
;
179 if (cache
->destructor
) {
180 cache
->destructor(ptr
, NULL
);
185 pthread_mutex_unlock(&cache
->mutex
);
188 #endif // HAVE_UMEM_H