|
|
| version 1.1.2.5, 2003/03/04 12:38:15 | version 1.34, 2017/11/18 17:42:39 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: memory reference counting classes decls. | Parser: memory reference counting classes decls. |
| Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001-2017 Art. Lebedev Studio (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| */ | */ |
| Line 9 | Line 9 |
| #ifndef PA_MEMORY_H | #ifndef PA_MEMORY_H |
| #define PA_MEMORY_H | #define PA_MEMORY_H |
| static const char* IDENT_MEMORY_H="$Date$"; | #define IDENT_PA_MEMORY_H "$Id$" |
| // include | // include |
| #include "pa_config_includes.h" | #include "pa_config_includes.h" |
| #include "gc.h" | |
| #include <new> | |
| #ifdef XML | // define destructors use for Array, Hash and VMethodFrame |
| # include "gdome.h" | #define USE_DESTRUCTORS |
| // for xmlChar | // std::basic_stringstream used in ^table.csv-string[] is compatible with delete usage check only under Debian 9 |
| # include "libxml/tree.h" | // #define CHECK_DELETE_USAGE |
| #endif | |
| inline void* pa_gc_malloc(size_t size) { return GC_MALLOC(size); } | |
| inline void* pa_gc_malloc_atomic(size_t size) { return GC_MALLOC_ATOMIC(size); } | |
| inline void* pa_gc_realloc(void* ptr, size_t size) { return GC_REALLOC(ptr, size); } | |
| inline void pa_gc_free(void* ptr) { GC_FREE(ptr); } | |
| // forwards | // forwards |
| void *pa_fail_alloc(char *what, size_t size); | void *pa_fail_alloc(const char* what, size_t size); |
| // inlines | // inlines |
| inline void *pa_malloc(size_t size) { | inline void *pa_malloc(size_t size) { |
| if(void *result=malloc(size)) | if(void *result=pa_gc_malloc(size)) |
| return result; | return result; |
| return pa_fail_alloc("allocate", size); | return pa_fail_alloc("allocate", size); |
| } | } |
| inline void *pa_calloc(size_t size) { | inline void *pa_malloc_atomic(size_t size) { |
| if(void *result=calloc(1, size)) | if(void *result=pa_gc_malloc_atomic(size)) |
| return result; | return result; |
| return pa_fail_alloc("allocate clean", size); | return pa_fail_alloc("allocate clean", size); |
| } | } |
| /// @a length may be null, which mean "autocalc it" | |
| inline char *pa_strdup(const char* auto_variable_never_null, size_t helper_length=0) { | |
| size_t known_length= helper_length ? helper_length : strlen(auto_variable_never_null); | |
| size_t size=known_length+1; | |
| if(char *result=static_cast<char*>(pa_gc_malloc_atomic(size))) { | |
| memcpy(result, auto_variable_never_null, known_length); | |
| result[known_length]=0; | |
| return result; | |
| } | |
| return static_cast<char*>(pa_fail_alloc("allocate clean", size)); | |
| } | |
| inline void pa_free(void *ptr) { | inline void pa_free(void *ptr) { |
| free(ptr); | pa_gc_free(ptr); |
| } | } |
| inline void *pa_realloc(void *ptr, size_t size) { | inline void *pa_realloc(void *ptr, size_t size) { |
| if(void *result=realloc(ptr, size)) | if(void *result=pa_gc_realloc(ptr, size)) |
| return result; | return result; |
| return pa_fail_alloc("reallocate to", size); | return pa_fail_alloc("reallocate to", size); |
| } | } |
| // forwards | /// memory allocation/dallocation goes via pa_malloc/pa_free. |
| class PA_Allocated { | |
| class Exception; | |
| class String; | |
| class Charset; | |
| class GdomeDOMString_auto_ptr; | |
| template<typename T> class object_ptr { | |
| T *ptr; | |
| public: | public: |
| typedef T element_type; | /// the sole: instances allocated using our functions |
| static void *operator new(size_t size) { | |
| explicit object_ptr(T *ptr = 0) { | return pa_malloc(size); |
| this->ptr=ptr; | |
| if(ptr) | |
| ptr->ref(); | |
| } | |
| 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(); | |
| if(ptr) | |
| 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 { | static void operator delete(void *ptr) { |
| return ptr; | pa_free(ptr); |
| } | } |
| operator bool() const { | static void *operator new[](size_t size) { |
| return get()!=0; | return pa_malloc(size); |
| } | } |
| bool operator !() const { | static void operator delete[](void *ptr) { |
| return get()==0; | pa_free(ptr); |
| } | } |
| }; | }; |
| #define DECLARE_OBJECT_PTR(name) \ | // new(PointerFreeGC)/new(PointerGC) should be used to allocate types not inherited from PA_Allocated |
| typedef object_ptr<name> name##Ptr | |
| /// TEMPLATE CLASS smart_ptr, stolen from stl:auto_ptr & renamed field/params [not compiled on gcc] | #define PointerFreeGC (true) |
| template<class T> | #define PointerGC (false) |
| class smart_ptr { | |
| bool owns; | inline void *operator new[] (size_t size, bool pointer_free) { |
| T *ptr; | return pointer_free ? pa_malloc_atomic(size) : pa_malloc(size); |
| public: | } |
| typedef T element_type; | |
| explicit smart_ptr(T *aptr = 0) | inline void *operator new (size_t size, bool pointer_free) { |
| : owns(aptr != 0), ptr(aptr) {} | return pointer_free ? pa_malloc_atomic(size) : pa_malloc(size); |
| smart_ptr(const smart_ptr<T>& src) | } |
| : owns(src.owns), ptr(src.release()) {} | |
| smart_ptr<T>& operator=(const smart_ptr<T>& src) | /// Base for all Parser classes |
| {if (this != &src) | typedef PA_Allocated PA_Object; |
| {if (ptr != src.get()) | |
| {if (owns) | |
| delete[] ptr; | |
| owns = src.owns; } | |
| else if (src.owns) | |
| owns = true; | |
| ptr = src.release(); } | |
| return (*this); } | |
| ~smart_ptr() | |
| {if (owns) | |
| delete[] ptr; } | |
| T& operator*() const | |
| {return (*get()); } | |
| T *get() const | |
| {return ptr; } | |
| T *release() const | |
| {((smart_ptr<T> *)this)->owns = false; | |
| return (ptr); } | |
| operator bool() const { | |
| return get()!=0; | |
| } | |
| bool operator !() const { | |
| return get()==0; | |
| } | |
| operator T*() const { | |
| return ptr; | |
| } | |
| }; | |
| // defines | // defines |
| #define override | #define override |
| #define rethrow throw | #define rethrow throw |
| // memory | #if defined(_MSC_VER) || (__cplusplus>=201103L) |
| #define PA_THROW(what) | |
| #else | |
| #define PA_THROW(what) throw(what) | |
| #endif | |
| inline void *operator new[] (size_t size) { | #ifndef _MSC_VER |
| return pa_malloc(size); | |
| } | |
| inline void *operator new[] (size_t size, int /*zero, just flag to use calloc instead of malloc*/) { | |
| return pa_calloc(size); | |
| } | |
| inline void operator delete[] (void *ptr) { | |
| pa_free(ptr); | |
| } | |
| inline void operator delete (void *ptr) { | |
| pa_free(ptr); | |
| } | |
| class PA_Allocated { | // regular new/delete are disabled from accidental use |
| 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 free(void *ptr) { | |
| pa_free(ptr); | |
| } | |
| static void *realloc(void *ptr, size_t size) { | |
| return pa_realloc(ptr, size); | |
| } | |
| }; | void *new_disabled(); |
| void delete_disabled(); | |
| /** | inline void *operator new[] (std::size_t) PA_THROW(std::bad_alloc){ return new_disabled(); } |
| Base for all Parser classes, memory allocation/dallocation goes via pa_malloc/pa_free. | inline void operator delete[](void *) throw(){ delete_disabled(); } |
| */ | |
| class PA_Object: public PA_Allocated { | |
| mutable unsigned long freferences; | |
| public: | |
| PA_Object(): freferences(0) {} | |
| virtual ~PA_Object() {} | |
| void ref() const { | |
| freferences++; | |
| } | |
| void unref() const { | |
| if(freferences) { | |
| if(--freferences==0) | |
| delete this; | |
| } | |
| } | |
| }; | |
| DECLARE_OBJECT_PTR(PA_Object); | |
| // convinient types | inline void *operator new(std::size_t) PA_THROW(std::bad_alloc){ return new_disabled(); } |
| #ifdef CHECK_DELETE_USAGE | |
| inline void operator delete(void *) throw(){ delete_disabled(); } | |
| #endif | |
| typedef smart_ptr<char> CharPtr; | // other regular allocators as disabled from accidental use as well |
| void *calloc_disabled(); | |
| void *malloc_disabled(); | |
| void *realloc_disabled(); | |
| void free_disabled(); | |
| char *strdup_disabled(); | |
| inline void *calloc(size_t) { return calloc_disabled(); } | |
| inline void *malloc(size_t) { return malloc_disabled(); } | |
| inline void *realloc(void *, size_t) { return realloc_disabled(); } | |
| inline void free(void *) { free_disabled(); } | |
| inline char *strdup(const char*, size_t){ return strdup_disabled(); } | |
| #endif | |
| #endif | #endif |