|
|
| version 1.19, 2001/01/30 13:43:42 | version 1.86.2.24, 2003/02/03 13:01:06 |
|---|---|
| Line 1 | Line 1 |
| /* | /** @file |
| $Id$ | Parser: Parser: reference counting classes decls. |
| Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) | |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | |
| */ | */ |
| #ifndef PA_POOL_H | #ifndef PA_POOL_H |
| #define PA_POOL_H | #define PA_POOL_H |
| #include <stddef.h> | static const char* IDENT_POOL_H="$Date$"; |
| // include | |
| #include "pa_config_includes.h" | |
| #ifdef XML | |
| # include "gdome.h" | |
| // for xmlChar | |
| # include "libxml/tree.h" | |
| #endif | |
| // forwards | |
| void *pa_malloc(size_t size); | |
| void *pa_calloc(size_t size); | |
| void pa_free(void *ptr); | |
| void *pa_realloc(void *ptr, size_t size); | |
| class Exception; | |
| class String; | |
| class Charset; | |
| class GdomeDOMString_auto_ptr; | |
| /* * | |
| Pool mechanizm allows users not to free up allocated memory, | |
| leaving that problem to 'pools'. | |
| #include "pa_string.h" | @see Pooled |
| #include "pa_hash.h" | * / |
| #include "pa_array.h" | |
| //#include "pa_table.h" | |
| #include "pa_exception.h" | |
| class Pool { | class Pool { |
| public: | public: |
| // Exception to report pool errors | Pool(void *astorage); |
| Pool(Exception& aexception) : fexception(aexception) {} | |
| ~Pool() {} | |
| Exception& exception() { return fexception; } | //{@ statistics |
| size_t total_allocated() { return ftotal_allocated; } | |
| void *malloc(size_t size) { | unsigned int total_times() { return ftotal_times; } |
| return check(real_malloc(size), size); | //}@ |
| void set_context(void *acontext) { fcontext=acontext; } | |
| void *get_context() { return fcontext; } | |
| /// allocates some bytes on pool | |
| void *malloc(size_t size, int place=0) { | |
| return check(real_malloc(size, place), size); | |
| } | } |
| /// allocates some bytes clearing them with zeros | |
| void *calloc(size_t size) { | void *calloc(size_t size) { |
| return check(real_calloc(size), size); | return check(real_calloc(size), size); |
| } | } |
| String& make_string() { | /// registers a routine to clean up non-pooled allocations |
| return *new(*this) String(*this); | void register_cleanup(void (*cleanup) (void *), void *data) { |
| if(!real_register_cleanup(cleanup, data)) | |
| fail_register_cleanup(); | |
| } | } |
| Hash& make_hash() { | |
| return *new(*this) Hash(*this, false); | //{@ helpers |
| void *copy(const void *buf, const size_t size); | |
| char *copy(const char* cstr); | |
| //}@ | |
| //{@ source charset | |
| void set_source_charset(Charset& acharset); | |
| Charset& get_source_charset(); | |
| //}@ | |
| //{@ client charset | |
| void set_client_charset(Charset& charset); | |
| Charset& get_client_charset(); | |
| //}@ | |
| #ifdef XML | |
| /// @see Charset::transcode_cstr(xmlChar *s); | |
| const char* transcode_cstr(xmlChar *s); | |
| /// @see Charset::transcode(xmlChar *s); | |
| String& transcode(xmlChar *s | |
| #ifndef NO_STRING_ORIGIN | |
| , const String *origin | |
| #endif | |
| ); | |
| /// @see Charset::transcode_cstr(GdomeDOMString *s); | |
| const char* transcode_cstr(GdomeDOMString *s); | |
| /// @see Charset::transcode(GdomeDOMString *s); | |
| String& transcode(GdomeDOMString *s | |
| #ifndef NO_STRING_ORIGIN | |
| , const String *origin | |
| #endif | |
| ); | |
| /// @see Charset::transcode_cstr(const char* buf, size_t buf_size=0); | |
| xmlChar *transcode_buf2xchar(const char* buf, size_t buf_size=0); | |
| /// @see Charset::transcode(const String& s) | |
| GdomeDOMString_auto_ptr transcode(const String& s); | |
| #endif | |
| private: | |
| void *fstorage; | |
| void *fcontext; | |
| Charset *source_charset; | |
| Charset *client_charset; | |
| private: | |
| //{ | |
| /// @name implementation defined | |
| void *real_malloc(size_t size, int place); | |
| void *real_calloc(size_t size); | |
| bool real_register_cleanup(void (*cleanup) (void *), void *data); | |
| //} | |
| private: | |
| /// checks whether mem allocated OK. throws exception otherwise | |
| void *check(void *ptr, size_t size) { | |
| if(ptr) { | |
| ftotal_allocated+=size; | |
| ftotal_times++; | |
| return ptr; | |
| } | |
| fail_alloc(size); | |
| // never reached | |
| return 0; | |
| } | } |
| Hash& make_thread_safe_hash() { | /// throws allocation exception |
| return *new(*this) Hash(*this, true); | void fail_alloc(size_t size) const; |
| /// throws register cleanup exception | |
| void fail_register_cleanup() const; | |
| private: // statistics | |
| size_t ftotal_allocated; | |
| unsigned int ftotal_times; | |
| private: //disabled | |
| Pool(const Pool&); | |
| Pool& operator= (const Pool&); | |
| }; | |
| */ | |
| /** | |
| Base for all classes that are allocated in 'pools'. | |
| Holds Pool object. Contains useful wrappers to it's methods. | |
| @see NEW | |
| * / | |
| // all classes that are members parents of packed class [String] | |
| // sould be packed also to avoid sparc odd st/lduh problem | |
| #include "pa_pragma_pack_begin.h" | |
| class Pooled { | |
| // the pool i'm allocated on | |
| Pool *fpool; | |
| public: | |
| /// the Pooled-sole: Pooled instances can be allocated in Pool rather then on heap | |
| static void *operator new(size_t size, Pool& apool) { | |
| return apool.malloc(size, 1); | |
| } | } |
| Array& make_array() { | |
| return *new(*this) Array(*this); | Pooled(Pool& apool) : fpool(&apool) {} |
| /// my pool | |
| Pool& pool() const { return *fpool; } | |
| /** used for moving objects from one pool to another. | |
| in between object can have no pool and can not be used | |
| @see SQL_Driver_manager | |
| * / | |
| void set_pool(Pool *apool) { fpool=apool; } | |
| //{ | |
| /// @name useful wrapper around pool | |
| void *malloc(size_t size, int place=0) const { return fpool->malloc(size, place); } | |
| void *calloc(size_t size) const { return fpool->calloc(size); } | |
| void register_cleanup(void (*cleanup) (void *), void *data) { fpool->register_cleanup(cleanup, data); } | |
| void *copy(const void *buf, const size_t size) { return fpool->copy(buf, size); } | |
| char *copy(const char* cstr) { return fpool->copy(cstr); } | |
| #ifdef XML | |
| const char* transcode_cstr(GdomeDOMString *s) { return fpool->transcode_cstr(s); } | |
| String& transcode(GdomeDOMString *s | |
| #ifndef NO_STRING_ORIGIN | |
| , const String *origin | |
| #endif | |
| ) { | |
| return fpool->transcode(s | |
| #ifndef NO_STRING_ORIGIN | |
| , origin | |
| #endif | |
| ); | |
| } | } |
| Array& make_array(int initial_rows) { | |
| return *new(*this) Array(*this, initial_rows); | #endif |
| //} | |
| }; | |
| #include "pa_pragma_pack_end.h" | |
| /// useful macro for creating objects on current Pooled object Pooled::pool() | |
| #define NEW new(pool()) | |
| */ | |
| #define override | |
| #define rethrow throw | |
| inline void *operator new(size_t size) { | |
| return pa_malloc(size); | |
| } | |
| inline void operator delete(void *ptr) { | |
| pa_free(ptr); | |
| } | |
| class PA_Allocated { | |
| public: | |
| /// the sole: instances allocated using our functions | |
| static void *operator new(size_t size) { | |
| return pa_malloc(size); | |
| } | |
| static void operator delete(void *ptr) { | |
| pa_free(ptr); | |
| } | |
| static void *malloc(size_t size) { | |
| return pa_malloc(size); | |
| } | |
| static void *calloc(size_t size) { | |
| return pa_calloc(size); | |
| } | |
| static void *realloc(void *ptr, size_t size) { | |
| return pa_realloc(ptr, size); | |
| } | } |
| /*Table& make_table(char *afile, uint aline, Array *acolumns, int initial_rows) { | |
| return *new(this) Table(this, afile, aline, acolumns, initial_rows); | |
| }*/ | |
| protected: // pure virtuals | }; |
| virtual void *real_malloc(size_t size)=0; | /** |
| virtual void *real_calloc(size_t size)=0; | Base for all Parser classes, memory allocation/dallocation goes via pa_malloc/pa_free. |
| */ | |
| class PA_Object: public PA_Allocated { | |
| mutable unsigned long freferences; | |
| public: | |
| PA_Object(): freferences(0) {} | |
| virtual ~PA_Object()=0; | |
| void ref() const { | |
| freferences++; | |
| } | |
| void unref() const { | |
| if(freferences) { | |
| if(--freferences==0) | |
| delete this; | |
| } | |
| } | |
| }; | |
| protected: | |
| Exception& fexception; | template<typename T> class object_ptr { |
| T *ptr; | |
| public: | |
| typedef T element_type; | |
| // checks whether mem allocated OK. throws exception otherwise | explicit object_ptr(T *ptr = 0) { |
| void *check(void *ptr, size_t size) { | this->ptr=ptr; |
| if(!ptr) | if(ptr) |
| fexception.raise(0, 0, | ptr->ref(); |
| 0, | } |
| "Pool::_alloc(%u) returned NULL", size); | template<class B> object_ptr(const object_ptr<B>& src) { |
| this->ptr=src.get(); | |
| if(ptr) | |
| ptr->ref(); | |
| } | |
| object_ptr(const object_ptr<T>& src) { | |
| ptr=src.get(); | |
| ptr->ref(); | |
| } | |
| object_ptr(T *ptr, int) { | |
| this->ptr=ptr; | |
| } | |
| object_ptr<T>& operator=(const object_ptr<T>& src) { | |
| if(this!=&src) | |
| if(ptr!=src.get()) { | |
| if(ptr) | |
| ptr->unref(); | |
| ptr=src.get(); | |
| if(ptr) | |
| ptr->ref(); | |
| } | |
| return *this; | |
| } | |
| ~object_ptr() { | |
| if(ptr) | |
| ptr->unref(); | |
| } | |
| T& operator*() const { | |
| return *get(); | |
| } | |
| T *operator->() const { | |
| return get(); | |
| } | |
| T *get() const { | |
| return ptr; | return ptr; |
| } | } |
| operator bool() const { | |
| return get()!=0; | |
| } | |
| bool operator !() const { | |
| return get()==0; | |
| } | |
| }; | |
| private: //disabled | #define DECLARE_OBJECT_PTR(name) \ |
| typedef object_ptr<name> name##Ptr | |
| // Pool(const Pool&) {} | // typedef object_ptr<name> name##Ptr; \ |
| Pool& operator = (const Pool&) { return *this; } | // const object_ptr<name> name##PtrZero(0); |
| }; | |
| /// TEMPLATE CLASS smart_ptr, stolen from stl:auto_ptr & renamed field/params [not compiled on gcc] | |
| template<class T> | |
| class smart_ptr { | |
| bool owns; | |
| T *ptr; | |
| public: | |
| typedef T element_type; | |
| explicit smart_ptr(T *aptr = 0) | |
| : owns(aptr != 0), ptr(aptr) {} | |
| smart_ptr(const smart_ptr<T>& src) | |
| : owns(src.owns), ptr(src.release()) {} | |
| smart_ptr<T>& operator=(const smart_ptr<T>& src) | |
| {if (this != &src) | |
| {if (this.ptr != src.get()) | |
| {if (owns) | |
| delete this.ptr; | |
| owns = src.owns; } | |
| else if (src.owns) | |
| owns = true; | |
| this.ptr = src.release(); } | |
| return (*this); } | |
| ~smart_ptr() | |
| {if (owns) | |
| delete this.ptr; } | |
| T& operator*() const | |
| {return (*get()); } | |
| T *get() const | |
| {return (this.ptr); } | |
| T *release() const | |
| {((smart_ptr<T> *)this)->owns = false; | |
| return (this.ptr); } | |
| operator bool() const { | |
| return get()!=0; | |
| } | |
| operator T*() const { | |
| return ptr; | |
| } | |
| }; | |
| // convinient types | |
| typedef smart_ptr<char> CharPtr; | |
| const CharPtr CharPtrZero(0); | |
| #endif | #endif |