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
@@ -34,3 +34,7 @@
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
@@ -43,3 +47,4 @@
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
@@ -62,29 +67,95 @@
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 }
@@ -92,5 +163,4 @@ void icalmemory_add_tmp_buffer(void* buf)
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 }
@@ -98,7 +168,11 @@ void icalmemory_add_tmp_buffer(void* buf)
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*
@@ -126,15 +200,19 @@ icalmemory_tmp_buffer (size_t size)
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}
@@ -143,3 +221,3 @@ void icalmemory_free_ring()
143 221
144/* Like strdup, but the buffer is on the ring. */ 222/** Like strdup, but the buffer is on the ring. */
145char* 223char*
@@ -172,4 +250,6 @@ icalmemory_free_tmp_buffer (void* buf)
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