summaryrefslogtreecommitdiffabout
path: root/libical/src/libical/icalmemory.c
Unidiff
Diffstat (limited to 'libical/src/libical/icalmemory.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libical/src/libical/icalmemory.c148
1 files changed, 114 insertions, 34 deletions
diff --git a/libical/src/libical/icalmemory.c b/libical/src/libical/icalmemory.c
index 297ead8..058ef37 100644
--- a/libical/src/libical/icalmemory.c
+++ b/libical/src/libical/icalmemory.c
@@ -32,7 +32,11 @@
32 32
33 ======================================================================*/ 33 ======================================================================*/
34 34
35/* libical often passes strings back to the caller. To make these 35/**
36 * @file icalmemory.c
37 * @brief Common memory management routines.
38 *
39 * libical often passes strings back to the caller. To make these
36 * interfaces simple, I did not want the caller to have to pass in a 40 * interfaces simple, I did not want the caller to have to pass in a
37 * memory buffer, but having libical pass out newly allocated memory 41 * memory buffer, but having libical pass out newly allocated memory
38 * makes it difficult to de-allocate the memory. 42 * makes it difficult to de-allocate the memory.
@@ -41,7 +45,8 @@
41 * out references to memory which the caller does not own, and be able 45 * out references to memory which the caller does not own, and be able
42 * to de-allocate the memory later. The ring allows libical to have 46 * to de-allocate the memory later. The ring allows libical to have
43 * several buffers active simultaneously, which is handy when creating 47 * several buffers active simultaneously, which is handy when creating
44 * string representations of components. */ 48 * string representations of components.
49 */
45 50
46#define ICALMEMORY_C 51#define ICALMEMORY_C
47 52
@@ -60,47 +65,116 @@
60#include <stdlib.h> /* for malloc, realloc */ 65#include <stdlib.h> /* for malloc, realloc */
61#include <string.h> /* for memset(), strdup */ 66#include <string.h> /* for memset(), strdup */
62 67
63#define BUFFER_RING_SIZE 25 68#ifdef WIN32
69#include <windows.h>
70#endif
71
72#define BUFFER_RING_SIZE 2500
64#define MIN_BUFFER_SIZE 200 73#define MIN_BUFFER_SIZE 200
65 74
75
76/* HACK. Not threadsafe */
77
78typedef struct {
79 int pos;
80 void *ring[BUFFER_RING_SIZE];
81} buffer_ring;
82
66void icalmemory_free_tmp_buffer (void* buf); 83void icalmemory_free_tmp_buffer (void* buf);
84void icalmemory_free_ring_byval(buffer_ring *br);
67 85
86static buffer_ring* global_buffer_ring = 0;
68 87
69/* HACK. Not threadsafe */ 88#ifdef HAVE_PTHREAD
70void* buffer_ring[BUFFER_RING_SIZE]; 89#include <pthread.h>
71int buffer_pos = -1;
72int initialized = 0;
73 90
74/* Add an existing buffer to the buffer ring */ 91static pthread_key_t ring_key;
75void icalmemory_add_tmp_buffer(void* buf) 92static pthread_once_t ring_key_once = PTHREAD_ONCE_INIT;
76{ 93
77 /* I don't think I need this -- I think static arrays are 94static void ring_destroy(void * buf) {
78 initialized to 0 as a standard part of C, but I am not sure. */ 95 if (buf) icalmemory_free_ring_byval((buffer_ring *) buf);
79 if (initialized == 0){ 96 pthread_setspecific(ring_key, NULL);
97}
98
99static void ring_key_alloc(void) {
100 pthread_key_create(&ring_key, ring_destroy);
101}
102#endif
103
104
105static buffer_ring * buffer_ring_new(void) {
106 buffer_ring *br;
80 int i; 107 int i;
108
109 br = (buffer_ring *)malloc(sizeof(buffer_ring));
110
81 for(i=0; i<BUFFER_RING_SIZE; i++){ 111 for(i=0; i<BUFFER_RING_SIZE; i++){
82 buffer_ring[i] = 0; 112 br->ring[i] = 0;
83 } 113 }
84 initialized = 1; 114 br->pos = 0;
115 return(br);
116}
117
118
119#ifdef HAVE_PTHREAD
120static buffer_ring* get_buffer_ring_pthread(void) {
121 buffer_ring *br;
122
123 pthread_once(&ring_key_once, ring_key_alloc);
124
125 br = pthread_getspecific(ring_key);
126
127 if (!br) {
128 br = buffer_ring_new();
129 pthread_setspecific(ring_key, br);
85 } 130 }
131 return(br);
132}
133#endif
134
135/* get buffer ring via a single global for a non-threaded program */
136static buffer_ring* get_buffer_ring_global(void) {
137 if (global_buffer_ring == 0) {
138 global_buffer_ring = buffer_ring_new();
139 }
140 return(global_buffer_ring);
141}
142
143static buffer_ring *get_buffer_ring(void) {
144#ifdef HAVE_PTHREAD
145 return(get_buffer_ring_pthread());
146#else
147 return get_buffer_ring_global();
148#endif
149}
150
151
152/** Add an existing buffer to the buffer ring */
153void icalmemory_add_tmp_buffer(void* buf)
154{
155 buffer_ring *br = get_buffer_ring();
156
86 157
87 /* Wrap around the ring */ 158 /* Wrap around the ring */
88 if(++buffer_pos == BUFFER_RING_SIZE){ 159 if(++(br->pos) == BUFFER_RING_SIZE){
89 buffer_pos = 0; 160 br->pos = 0;
90 } 161 }
91 162
92 /* Free buffers as their slots are overwritten */ 163 /* Free buffers as their slots are overwritten */
93 if ( buffer_ring[buffer_pos] != 0){ 164 if ( br->ring[br->pos] != 0){
94 free( buffer_ring[buffer_pos]); 165 free( br->ring[br->pos]);
95 buffer_ring[buffer_pos] = 0;
96 } 166 }
97 167
98 /* Assign the buffer to a slot */ 168 /* Assign the buffer to a slot */
99 buffer_ring[buffer_pos] = buf; 169 br->ring[br->pos] = buf;
100} 170}
101 171
102/* Create a new temporary buffer on the ring. Libical owns these and 172
103 wil deallocate them. */ 173/**
174 * Create a new temporary buffer on the ring. Libical owns these and
175 * will deallocate them.
176 */
177
104void* 178void*
105icalmemory_tmp_buffer (size_t size) 179icalmemory_tmp_buffer (size_t size)
106{ 180{
@@ -124,24 +198,28 @@ icalmemory_tmp_buffer (size_t size)
124 return buf; 198 return buf;
125} 199}
126 200
127void icalmemory_free_ring() 201/** get rid of this buffer ring */
128{ 202void icalmemory_free_ring_byval(buffer_ring *br) {
129
130 int i; 203 int i;
131 for(i=0; i<BUFFER_RING_SIZE; i++){ 204 for(i=0; i<BUFFER_RING_SIZE; i++){
132 if ( buffer_ring[i] != 0){ 205 if ( br->ring[i] != 0){
133 free( buffer_ring[i]); 206 free( br->ring[i]);
134 } 207 }
135 buffer_ring[i] = 0; 208 }
136 } 209 free(br);
210}
137 211
138 initialized = 1; 212void icalmemory_free_ring()
213{
214 buffer_ring *br;
215 br = get_buffer_ring();
139 216
217 icalmemory_free_ring_byval(br);
140} 218}
141 219
142 220
143 221
144/* Like strdup, but the buffer is on the ring. */ 222/** Like strdup, but the buffer is on the ring. */
145char* 223char*
146icalmemory_tmp_copy(const char* str) 224icalmemory_tmp_copy(const char* str)
147{ 225{
@@ -170,8 +248,10 @@ icalmemory_free_tmp_buffer (void* buf)
170} 248}
171 249
172 250
173/* These buffer routines create memory the old fashioned way -- so the 251/*
174 caller will have to delocate the new memory */ 252 * These buffer routines create memory the old fashioned way -- so the
253 * caller will have to deallocate the new memory
254 */
175 255
176void* icalmemory_new_buffer(size_t size) 256void* icalmemory_new_buffer(size_t size)
177{ 257{