|
|
| version 1.61, 2001/10/05 17:33:50 | version 1.86.2.1, 2003/01/22 15:39:07 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: pool class decl. | Parser: Parser: reference counting classes decls. |
| Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| $Id$ | |
| */ | */ |
| #ifndef PA_POOL_H | #ifndef PA_POOL_H |
| #define PA_POOL_H | #define PA_POOL_H |
| static const char* IDENT_POOL_H="$Date$"; | |
| #include "pa_config_includes.h" | #include "pa_config_includes.h" |
| #ifdef XML | #ifdef XML |
| #include <XalanDOM/XalanDOMString.hpp> | # include "gdome.h" |
| #include <util/TransService.hpp> | // for xmlChar |
| #include <PlatformSupport/XSLException.hpp> | # include "libxml/tree.h" |
| #include <sax/SAXException.hpp> | |
| #include <sax/SAXParseException.hpp> | |
| #include <util/XMLException.hpp> | |
| #endif | #endif |
| 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); | |
| // forwards | // forwards |
| class Exception; | class Exception; |
| class Temp_exception; | |
| class String; | class String; |
| class Charset; | |
| class GdomeDOMString_auto_ptr; | |
| /** | /* * |
| Pool mechanizm allows users not to free up allocated memory, | Pool mechanizm allows users not to free up allocated memory, |
| leaving that problem to 'pools'. | leaving that problem to 'pools'. |
| Also holds Exception object, which can be temporary set using | |
| Temp_exception auto-object. | |
| @see Pooled | @see Pooled |
| */ | * / |
| class Pool { | class Pool { |
| friend Temp_exception; | |
| public: | public: |
| Pool(void *astorage); | Pool(void *astorage); |
| ~Pool(); | |
| void set_context(void *acontext) { fcontext=acontext; } | //{@ statistics |
| void *context() { return fcontext; } | size_t total_allocated() { return ftotal_allocated; } |
| unsigned int total_times() { return ftotal_times; } | |
| //}@ | |
| void set_tag(void *atag) { ftag=atag; } | void set_context(void *acontext) { fcontext=acontext; } |
| void *tag() { return ftag; } | void *get_context() { return fcontext; } |
| /// allocates some bytes on pool | /// allocates some bytes on pool |
| void *malloc(size_t size/*, int place=0*/) { | void *malloc(size_t size, int place=0) { |
| return check(real_malloc(size/*, place*/), size); | return check(real_malloc(size, place), size); |
| } | } |
| /// allocates some bytes clearing them with zeros | /// allocates some bytes clearing them with zeros |
| void *calloc(size_t size) { | void *calloc(size_t size) { |
| Line 66 public: | Line 66 public: |
| fail_register_cleanup(); | fail_register_cleanup(); |
| } | } |
| /// current exception object of the pool | //{@ helpers |
| Exception& exception() const { return *fexception; } | 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(); | |
| //}@ | |
| /// resets transcoder if they change charset | #ifdef XML |
| void set_charset(const String &charset); | |
| /// returns current charset | /// @see Charset::transcode_cstr(xmlChar *s); |
| const String& get_charset() { return *charset; } | 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: | private: |
| void *fstorage; | void *fstorage; |
| void *fcontext; | void *fcontext; |
| void *ftag; | Charset *source_charset; |
| const String *charset; | Charset *client_charset; |
| private: | private: |
| //{ | //{ |
| /// @name implementation defined | /// @name implementation defined |
| void *real_malloc(size_t size/*, int place*/); | void *real_malloc(size_t size, int place); |
| void *real_calloc(size_t size); | void *real_calloc(size_t size); |
| bool real_register_cleanup(void (*cleanup) (void *), void *data); | bool real_register_cleanup(void (*cleanup) (void *), void *data); |
| //} | //} |
| Line 94 private: | Line 126 private: |
| /// checks whether mem allocated OK. throws exception otherwise | /// checks whether mem allocated OK. throws exception otherwise |
| void *check(void *ptr, size_t size) { | void *check(void *ptr, size_t size) { |
| if(ptr) | if(ptr) { |
| ftotal_allocated+=size; | |
| ftotal_times++; | |
| return ptr; | return ptr; |
| } | |
| fail_alloc(size); | fail_alloc(size); |
| Line 108 private: | Line 143 private: |
| /// throws register cleanup exception | /// throws register cleanup exception |
| void fail_register_cleanup() const; | void fail_register_cleanup() const; |
| private: // exception handling | private: // statistics |
| // exception replacement mechanism is 'private'zed from direct usage | size_t ftotal_allocated; |
| // Temp_exception object enforces paired set/restore | unsigned int ftotal_times; |
| Exception *set_exception(Exception *e){ | |
| Exception *r=fexception; | |
| fexception=e; | |
| return r; | |
| } | |
| void restore_exception(Exception *e) { | |
| fexception=e; | |
| } | |
| private: | |
| // current request's exception object | |
| Exception *fexception; | |
| #ifdef XML | |
| public: | |
| /// converts Xalan string to char * | |
| const char *transcode_cstr(const XalanDOMString& s); | |
| /// converts Xalan string to parser String | |
| String& transcode(const XalanDOMString& s); | |
| /// converts XSL exception to parser exception | |
| void _throw(const String *source, const XSLException& e); | |
| /// converts SAX exception to parser exception | |
| void _throw(const String *source, const SAXException& e); | |
| /// converts SAX parse exception to parser exception | |
| void _throw(const String *source, const SAXParseException& e); | |
| /// converts XML exception to parser exception | |
| void _throw(const String *source, const XMLException& e); | |
| /// converts Xalan DOM exception to parser exception | |
| void _throw(const String *source, const XalanDOMException& e); | |
| private: | |
| void set_charset(const char *new_scharset); | |
| void update_transcoder(); | |
| private: | |
| XMLTranscoder *transcoder; | |
| #endif | |
| private: //disabled | private: //disabled |
| // Pool(const Pool&) {} | Pool(const Pool&); |
| Pool& operator = (const Pool&) { return *this; } | Pool& operator= (const Pool&); |
| }; | }; |
| */ | |
| /** | /** |
| Base for all classes that are allocated in 'pools'. | Base for all classes that are allocated in 'pools'. |
| Holds Pool object. Contains useful wrappers to it's methods. | Holds Pool object. Contains useful wrappers to it's methods. |
| @see NEW, Temp_exception | @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 { | class Pooled { |
| // the pool i'm allocated on | // the pool i'm allocated on |
| Pool *fpool; | Pool *fpool; |
| Line 175 public: | Line 174 public: |
| /// the Pooled-sole: Pooled instances can be allocated in Pool rather then on heap | /// the Pooled-sole: Pooled instances can be allocated in Pool rather then on heap |
| static void *operator new(size_t size, Pool& apool) { | static void *operator new(size_t size, Pool& apool) { |
| return apool.malloc(size/*, 1*/); | return apool.malloc(size, 1); |
| } | } |
| Pooled(Pool& apool) : fpool(&apool) {} | Pooled(Pool& apool) : fpool(&apool) {} |
| Line 186 public: | Line 185 public: |
| /** used for moving objects from one pool to another. | /** used for moving objects from one pool to another. |
| in between object can have no pool and can not be used | in between object can have no pool and can not be used |
| @see SQL_Driver_manager | @see SQL_Driver_manager |
| */ | * / |
| void set_pool(Pool *apool) { fpool=apool; } | void set_pool(Pool *apool) { fpool=apool; } |
| //{ | //{ |
| /// @name useful wrapper around pool | /// @name useful wrapper around pool |
| void *malloc(size_t size) const { return fpool->malloc(size); } | 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 *calloc(size_t size) const { return fpool->calloc(size); } |
| void register_cleanup(void (*cleanup) (void *), void *data) { fpool->register_cleanup(cleanup, data); } | void register_cleanup(void (*cleanup) (void *), void *data) { fpool->register_cleanup(cleanup, data); } |
| Exception& exception() const { return fpool->exception(); } | 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 | #ifdef XML |
| const char *transcode_cstr(const XalanDOMString& s) { return fpool->transcode_cstr(s); } | |
| String& transcode(const XalanDOMString& s) { return fpool->transcode(s); } | const char *transcode_cstr(GdomeDOMString *s) { return fpool->transcode_cstr(s); } |
| void _throw(const String *source, const XSLException& e) { fpool->_throw(source, e); } | String& transcode(GdomeDOMString *s |
| void _throw(const String *source, const SAXException& e) { fpool->_throw(source, e); } | #ifndef NO_STRING_ORIGIN |
| void _throw(const String *source, const SAXParseException& e) { fpool->_throw(source, e); } | , const String *origin |
| void _throw(const String *source, const XMLException& e) { fpool->_throw(source, e); } | #endif |
| void _throw(const String *source, const XalanDOMException& e) { fpool->_throw(source, e); } | ) { |
| return fpool->transcode(s | |
| #ifndef NO_STRING_ORIGIN | |
| , origin | |
| #endif | |
| ); | |
| } | |
| #endif | #endif |
| //} | //} |
| }; | }; |
| #include "pa_pragma_pack_end.h" | |
| /// useful macro for creating objects on current Pooled object Pooled::pool() | /// useful macro for creating objects on current Pooled object Pooled::pool() |
| #define NEW new(pool()) | #define NEW new(pool()) |
| */ | |
| /** | /** |
| Auto-object used for temporary changing Pool's exception(). | Base for all Parser classes, memory allocation/dallocation goes via pa_malloc/pa_free. |
| */ | |
| Use by with these macros: | class PA_Object { |
| @code | mutable unsigned long references_count; |
| TRY { | public: |
| // ... | PA_Object(): references_count(0) {} |
| if(?) | void add_ref() { |
| THROW(?); | references_count++; |
| // ... | } |
| } CATCH(e) { | void release() { |
| // code, using e fields | if(references_count) { |
| // e.comment() | if(--references_count==0) |
| delete this; | |
| } | } |
| END_CATCH | } |
| @endcode | |
| @see TRY, THROW | |
| */ | |
| class Temp_exception { | |
| Pool& fpool; | |
| Exception *saved_exception; | |
| public: | public: |
| Temp_exception(Pool& apool, Exception& exception) : | /// the PA_Object -sole: instances allocated using our functions |
| fpool(apool), | static void *operator new(size_t size) { |
| saved_exception(apool.set_exception(&exception)) { | return pa_malloc(size); |
| } | } |
| ~Temp_exception() { | static void operator delete(void *ptr) { |
| fpool.restore_exception(saved_exception); | pa_free(ptr); |
| } | } |
| }; | }; |
| #define XTRY(pool) \ | template<class T> class auto_ptr { |
| { \ | T *ptr; |
| Exception temp_exception; \ | public: |
| Temp_exception le(pool, temp_exception); \ | typedef T element_type; |
| if(setjmp(temp_exception.mark)==0) | explicit auto_ptr(T *ptr = 0) { |
| this->ptr=ptr; | |
| #define XTHROW(exception) exception._throw | if(ptr) |
| #define XCATCH(e) \ | ptr->add_ref(); |
| else{ \ | } |
| Exception& e=temp_exception; | auto_ptr(const auto_ptr<T>& src) { |
| ptr=src.get(); | |
| #define XEND_CATCH \ | ptr->add_ref(); |
| } \ | } |
| } | auto_ptr<T>& operator=(auto_ptr<T>& src) { |
| if(this!=&src) | |
| //@{ | if(ptr!=src.get()) { |
| /// @see Temp_exception | if(ptr) |
| #define TRY XTRY(pool()) | ptr->release(); |
| #define THROW XTHROW(exception()) | ptr=src.get(); |
| #define CATCH(e) XCATCH(e) | if(ptr) |
| #define END_CATCH XEND_CATCH | ptr->add_ref(); |
| } | |
| #define PTRY XTRY(pool) | } |
| #define PTHROW XTHROW(pool.exception()) | ~auto_ptr() { |
| #define PCATCH(e) XCATCH(e) | if(ptr) |
| #define PEND_CATCH XEND_CATCH | ptr->release(); |
| //@} | } |
| T& operator*() const { | |
| return *get(); | |
| } | |
| T *operator->() const { | |
| return get(); | |
| } | |
| T *get() const { | |
| return ptr; | |
| } | |
| }; | |
| #endif | #endif |