Header And Logo

PostgreSQL
| The world's most advanced open source database.

memory.c

Go to the documentation of this file.
00001 /* src/interfaces/ecpg/ecpglib/memory.c */
00002 
00003 #define POSTGRES_ECPG_INTERNAL
00004 #include "postgres_fe.h"
00005 
00006 #include "ecpg-pthread-win32.h"
00007 #include "ecpgtype.h"
00008 #include "ecpglib.h"
00009 #include "ecpgerrno.h"
00010 #include "extern.h"
00011 
00012 void
00013 ecpg_free(void *ptr)
00014 {
00015     free(ptr);
00016 }
00017 
00018 char *
00019 ecpg_alloc(long size, int lineno)
00020 {
00021     char       *new = (char *) calloc(1L, size);
00022 
00023     if (!new)
00024     {
00025         ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
00026         return NULL;
00027     }
00028 
00029     return (new);
00030 }
00031 
00032 char *
00033 ecpg_realloc(void *ptr, long size, int lineno)
00034 {
00035     char       *new = (char *) realloc(ptr, size);
00036 
00037     if (!new)
00038     {
00039         ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
00040         return NULL;
00041     }
00042 
00043     return (new);
00044 }
00045 
00046 char *
00047 ecpg_strdup(const char *string, int lineno)
00048 {
00049     char       *new;
00050 
00051     if (string == NULL)
00052         return NULL;
00053 
00054     new = strdup(string);
00055     if (!new)
00056     {
00057         ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
00058         return NULL;
00059     }
00060 
00061     return (new);
00062 }
00063 
00064 /* keep a list of memory we allocated for the user */
00065 struct auto_mem
00066 {
00067     void       *pointer;
00068     struct auto_mem *next;
00069 };
00070 
00071 #ifdef ENABLE_THREAD_SAFETY
00072 static pthread_key_t auto_mem_key;
00073 static pthread_once_t auto_mem_once = PTHREAD_ONCE_INIT;
00074 
00075 static void
00076 auto_mem_destructor(void *arg)
00077 {
00078     (void) arg;                 /* keep the compiler quiet */
00079     ECPGfree_auto_mem();
00080 }
00081 
00082 static void
00083 auto_mem_key_init(void)
00084 {
00085     pthread_key_create(&auto_mem_key, auto_mem_destructor);
00086 }
00087 
00088 static struct auto_mem *
00089 get_auto_allocs(void)
00090 {
00091     pthread_once(&auto_mem_once, auto_mem_key_init);
00092     return (struct auto_mem *) pthread_getspecific(auto_mem_key);
00093 }
00094 
00095 static void
00096 set_auto_allocs(struct auto_mem * am)
00097 {
00098     pthread_setspecific(auto_mem_key, am);
00099 }
00100 #else
00101 static struct auto_mem *auto_allocs = NULL;
00102 
00103 #define get_auto_allocs()       (auto_allocs)
00104 #define set_auto_allocs(am)     do { auto_allocs = (am); } while(0)
00105 #endif
00106 
00107 void
00108 ecpg_add_mem(void *ptr, int lineno)
00109 {
00110     struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), lineno);
00111 
00112     am->pointer = ptr;
00113     am->next = get_auto_allocs();
00114     set_auto_allocs(am);
00115 }
00116 
00117 void
00118 ECPGfree_auto_mem(void)
00119 {
00120     struct auto_mem *am = get_auto_allocs();
00121 
00122     /* free all memory we have allocated for the user */
00123     if (am)
00124     {
00125         do
00126         {
00127             struct auto_mem *act = am;
00128 
00129             am = am->next;
00130             ecpg_free(act->pointer);
00131             ecpg_free(act);
00132         } while (am);
00133         set_auto_allocs(NULL);
00134     }
00135 }
00136 
00137 void
00138 ecpg_clear_auto_mem(void)
00139 {
00140     struct auto_mem *am = get_auto_allocs();
00141 
00142     /* only free our own structure */
00143     if (am)
00144     {
00145         do
00146         {
00147             struct auto_mem *act = am;
00148 
00149             am = am->next;
00150             ecpg_free(act);
00151         } while (am);
00152         set_auto_allocs(NULL);
00153     }
00154 }