summaryrefslogtreecommitdiffabout
path: root/libical/src/libical/icalmemory.c
Side-by-side diff
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 @@
======================================================================*/
-/* libical often passes strings back to the caller. To make these
+/**
+ * @file icalmemory.c
+ * @brief Common memory management routines.
+ *
+ * libical often passes strings back to the caller. To make these
* interfaces simple, I did not want the caller to have to pass in a
* memory buffer, but having libical pass out newly allocated memory
* makes it difficult to de-allocate the memory.
@@ -41,7 +45,8 @@
* out references to memory which the caller does not own, and be able
* to de-allocate the memory later. The ring allows libical to have
* several buffers active simultaneously, which is handy when creating
- * string representations of components. */
+ * string representations of components.
+ */
#define ICALMEMORY_C
@@ -60,47 +65,116 @@
#include <stdlib.h> /* for malloc, realloc */
#include <string.h> /* for memset(), strdup */
-#define BUFFER_RING_SIZE 25
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#define BUFFER_RING_SIZE 2500
#define MIN_BUFFER_SIZE 200
+
+/* HACK. Not threadsafe */
+
+typedef struct {
+ int pos;
+ void *ring[BUFFER_RING_SIZE];
+} buffer_ring;
+
void icalmemory_free_tmp_buffer (void* buf);
+void icalmemory_free_ring_byval(buffer_ring *br);
+static buffer_ring* global_buffer_ring = 0;
-/* HACK. Not threadsafe */
-void* buffer_ring[BUFFER_RING_SIZE];
-int buffer_pos = -1;
-int initialized = 0;
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
-/* Add an existing buffer to the buffer ring */
-void icalmemory_add_tmp_buffer(void* buf)
-{
- /* I don't think I need this -- I think static arrays are
- initialized to 0 as a standard part of C, but I am not sure. */
- if (initialized == 0){
+static pthread_key_t ring_key;
+static pthread_once_t ring_key_once = PTHREAD_ONCE_INIT;
+
+static void ring_destroy(void * buf) {
+ if (buf) icalmemory_free_ring_byval((buffer_ring *) buf);
+ pthread_setspecific(ring_key, NULL);
+}
+
+static void ring_key_alloc(void) {
+ pthread_key_create(&ring_key, ring_destroy);
+}
+#endif
+
+
+static buffer_ring * buffer_ring_new(void) {
+ buffer_ring *br;
int i;
+
+ br = (buffer_ring *)malloc(sizeof(buffer_ring));
+
for(i=0; i<BUFFER_RING_SIZE; i++){
- buffer_ring[i] = 0;
+ br->ring[i] = 0;
}
- initialized = 1;
+ br->pos = 0;
+ return(br);
+}
+
+
+#ifdef HAVE_PTHREAD
+static buffer_ring* get_buffer_ring_pthread(void) {
+ buffer_ring *br;
+
+ pthread_once(&ring_key_once, ring_key_alloc);
+
+ br = pthread_getspecific(ring_key);
+
+ if (!br) {
+ br = buffer_ring_new();
+ pthread_setspecific(ring_key, br);
}
+ return(br);
+}
+#endif
+
+/* get buffer ring via a single global for a non-threaded program */
+static buffer_ring* get_buffer_ring_global(void) {
+ if (global_buffer_ring == 0) {
+ global_buffer_ring = buffer_ring_new();
+ }
+ return(global_buffer_ring);
+}
+
+static buffer_ring *get_buffer_ring(void) {
+#ifdef HAVE_PTHREAD
+ return(get_buffer_ring_pthread());
+#else
+ return get_buffer_ring_global();
+#endif
+}
+
+
+/** Add an existing buffer to the buffer ring */
+void icalmemory_add_tmp_buffer(void* buf)
+{
+ buffer_ring *br = get_buffer_ring();
+
/* Wrap around the ring */
- if(++buffer_pos == BUFFER_RING_SIZE){
- buffer_pos = 0;
+ if(++(br->pos) == BUFFER_RING_SIZE){
+ br->pos = 0;
}
/* Free buffers as their slots are overwritten */
- if ( buffer_ring[buffer_pos] != 0){
- free( buffer_ring[buffer_pos]);
- buffer_ring[buffer_pos] = 0;
+ if ( br->ring[br->pos] != 0){
+ free( br->ring[br->pos]);
}
/* Assign the buffer to a slot */
- buffer_ring[buffer_pos] = buf;
+ br->ring[br->pos] = buf;
}
-/* Create a new temporary buffer on the ring. Libical owns these and
- wil deallocate them. */
+
+/**
+ * Create a new temporary buffer on the ring. Libical owns these and
+ * will deallocate them.
+ */
+
void*
icalmemory_tmp_buffer (size_t size)
{
@@ -124,24 +198,28 @@ icalmemory_tmp_buffer (size_t size)
return buf;
}
-void icalmemory_free_ring()
-{
-
+/** get rid of this buffer ring */
+void icalmemory_free_ring_byval(buffer_ring *br) {
int i;
for(i=0; i<BUFFER_RING_SIZE; i++){
- if ( buffer_ring[i] != 0){
- free( buffer_ring[i]);
+ if ( br->ring[i] != 0){
+ free( br->ring[i]);
}
- buffer_ring[i] = 0;
- }
+ }
+ free(br);
+}
- initialized = 1;
+void icalmemory_free_ring()
+{
+ buffer_ring *br;
+ br = get_buffer_ring();
+ icalmemory_free_ring_byval(br);
}
-/* Like strdup, but the buffer is on the ring. */
+/** Like strdup, but the buffer is on the ring. */
char*
icalmemory_tmp_copy(const char* str)
{
@@ -170,8 +248,10 @@ icalmemory_free_tmp_buffer (void* buf)
}
-/* These buffer routines create memory the old fashioned way -- so the
- caller will have to delocate the new memory */
+/*
+ * These buffer routines create memory the old fashioned way -- so the
+ * caller will have to deallocate the new memory
+ */
void* icalmemory_new_buffer(size_t size)
{