Diffstat (limited to 'libical/src/libical/icalmemory.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libical/src/libical/icalmemory.c | 148 |
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 | |||
78 | typedef struct { | ||
79 | int pos; | ||
80 | void *ring[BUFFER_RING_SIZE]; | ||
81 | } buffer_ring; | ||
82 | |||
66 | void icalmemory_free_tmp_buffer (void* buf); | 83 | void icalmemory_free_tmp_buffer (void* buf); |
84 | void icalmemory_free_ring_byval(buffer_ring *br); | ||
67 | 85 | ||
86 | static buffer_ring* global_buffer_ring = 0; | ||
68 | 87 | ||
69 | /* HACK. Not threadsafe */ | 88 | #ifdef HAVE_PTHREAD |
70 | void* buffer_ring[BUFFER_RING_SIZE]; | 89 | #include <pthread.h> |
71 | int buffer_pos = -1; | ||
72 | int initialized = 0; | ||
73 | 90 | ||
74 | /* Add an existing buffer to the buffer ring */ | 91 | static pthread_key_t ring_key; |
75 | void icalmemory_add_tmp_buffer(void* buf) | 92 | static pthread_once_t ring_key_once = PTHREAD_ONCE_INIT; |
76 | { | 93 | |
77 | /* I don't think I need this -- I think static arrays are | 94 | static 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 | |||
99 | static void ring_key_alloc(void) { | ||
100 | pthread_key_create(&ring_key, ring_destroy); | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | |||
105 | static 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 | ||
120 | static 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 */ | ||
136 | static 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 | |||
143 | static 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 */ | ||
153 | void 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 | |||
104 | void* | 178 | void* |
@@ -126,15 +200,19 @@ icalmemory_tmp_buffer (size_t size) | |||
126 | 200 | ||
127 | void icalmemory_free_ring() | 201 | /** get rid of this buffer ring */ |
128 | { | 202 | void 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; | 212 | void 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. */ |
145 | char* | 223 | char* |
@@ -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 | ||