|
|
| version 1.19, 2001/01/30 13:43:42 | version 1.53, 2001/09/15 11:48:41 |
|---|---|
| Line 1 | Line 1 |
| /* | /** @file |
| $Id$ | Parser: pool class decl. |
| Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) | |
| Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) | |
| $Id$ | |
| */ | */ |
| #ifndef PA_POOL_H | #ifndef PA_POOL_H |
| #define PA_POOL_H | #define PA_POOL_H |
| #include <stddef.h> | #include "pa_config_includes.h" |
| class Exception; | |
| class Temp_exception; | |
| /** | |
| Pool mechanizm allows users not to free up allocated memory, | |
| leaving that problem to 'pools'. | |
| #include "pa_string.h" | Also holds Exception object, which can be temporary set using |
| #include "pa_hash.h" | Temp_exception auto-object. |
| #include "pa_array.h" | |
| //#include "pa_table.h" | @see Pooled |
| #include "pa_exception.h" | */ |
| class Pool { | class Pool { |
| friend Temp_exception; | |
| public: | public: |
| // Exception to report pool errors | Pool(void *astorage) : fstorage(astorage), fcontext(0), ftag(0), fexception(0) {} |
| Pool(Exception& aexception) : fexception(aexception) {} | |
| ~Pool() {} | void set_context(void *acontext) { fcontext=acontext; } |
| void *context() { return fcontext; } | |
| Exception& exception() { return fexception; } | void set_tag(void *atag) { ftag=atag; } |
| void *tag() { return ftag; } | |
| void *malloc(size_t size) { | /// allocates some bytes on pool |
| return check(real_malloc(size), size); | 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); |
| } | |
| Hash& make_hash() { | |
| return *new(*this) Hash(*this, false); | |
| } | |
| Hash& make_thread_safe_hash() { | |
| return *new(*this) Hash(*this, true); | |
| } | |
| Array& make_array() { | |
| return *new(*this) Array(*this); | |
| } | |
| Array& make_array(int initial_rows) { | |
| return *new(*this) Array(*this, initial_rows); | |
| } | |
| /*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 | /// current exception object of the pool |
| Exception& exception() const { return *fexception; } | |
| virtual void *real_malloc(size_t size)=0; | private: |
| virtual void *real_calloc(size_t size)=0; | |
| protected: | void *fstorage; |
| void *fcontext; | |
| void *ftag; | |
| Exception& fexception; | private: |
| //{ | |
| /// @name implementation defined | |
| void *real_malloc(size_t size/*, int place*/); | |
| void *real_calloc(size_t size); | |
| //} | |
| // checks whether mem allocated OK. throws exception otherwise | private: |
| /// 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) |
| fexception.raise(0, 0, | return ptr; |
| 0, | |
| "Pool::_alloc(%u) returned NULL", size); | fail(size); |
| return ptr; | // never reached |
| return 0; | |
| } | |
| /// throws proper exception | |
| void fail(size_t size) const; | |
| private: // exception handling | |
| // exception replacement mechanism is 'private'zed from direct usage | |
| // Temp_exception object enforces paired set/restore | |
| 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; | |
| private: //disabled | private: //disabled |
| // Pool(const Pool&) {} | // Pool(const Pool&) {} |
| Pool& operator = (const Pool&) { return *this; } | Pool& operator = (const Pool&) { return *this; } |
| }; | }; |
| /** | |
| Base for all classes that are allocated in 'pools'. | |
| Holds Pool object. Contains useful wrappers to it's methods. | |
| @see NEW, Temp_exception | |
| */ | |
| 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*/); | |
| } | |
| 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; } | |
| /// useful wrapper around pool | |
| void *malloc(size_t size) const { return fpool->malloc(size); } | |
| /// useful wrapper around pool | |
| void *calloc(size_t size) const { return fpool->calloc(size); } | |
| /// useful wrapper around pool | |
| void register_cleanup(void (*cleanup) (void *), void *data) { | |
| fpool->register_cleanup(cleanup, data); | |
| } | |
| /// useful wrapper around pool | |
| Exception& exception() const { return fpool->exception(); } | |
| }; | |
| /// useful macro for creating objects on current Pooled object Pooled::pool() | |
| #define NEW new(pool()) | |
| /** | |
| Auto-object used for temporary changing Pool's exception(). | |
| Use by with these macros: | |
| @code | |
| TRY { | |
| // ... | |
| if(?) | |
| THROW(?); | |
| // ... | |
| } CATCH(e) { | |
| // code, using e fields | |
| // e.comment() | |
| } | |
| END_CATCH | |
| @endcode | |
| @see TRY, THROW | |
| */ | |
| class Temp_exception { | |
| Pool& fpool; | |
| Exception *saved_exception; | |
| public: | |
| Temp_exception(Pool& apool, Exception& exception) : | |
| fpool(apool), | |
| saved_exception(apool.set_exception(&exception)) { | |
| } | |
| ~Temp_exception() { | |
| fpool.restore_exception(saved_exception); | |
| } | |
| }; | |
| #define XTRY(pool) \ | |
| { \ | |
| Exception temp_exception; \ | |
| Temp_exception le(pool, temp_exception); \ | |
| if(setjmp(temp_exception.mark)==0) | |
| #define XTHROW(exception) exception._throw | |
| #define XCATCH(e) \ | |
| else{ \ | |
| Exception& e=temp_exception; | |
| #define XEND_CATCH \ | |
| } \ | |
| } | |
| //@{ | |
| /// @see Temp_exception | |
| #define TRY XTRY(pool()) | |
| #define THROW XTHROW(exception()) | |
| #define CATCH(e) XCATCH(e) | |
| #define END_CATCH XEND_CATCH | |
| #define PTRY XTRY(pool) | |
| #define PTHROW XTHROW(pool.exception()) | |
| #define PCATCH(e) XCATCH(e) | |
| #define PEND_CATCH XEND_CATCH | |
| //@} | |
| #endif | #endif |