File:  [parser3project] / parser3 / src / include / pa_pool.h
Revision 1.86.2.20: download - view: text, annotated - select for diffs - revision graph
Thu Jan 30 11:19:30 2003 UTC (23 years, 5 months ago) by paf
Diff to: branchpoint 1.86: preferred, unified
vstateless_class compiled

/** @file
	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
#define PA_POOL_H

static const char* IDENT_POOL_H="$Date: 2003/01/30 11:19:30 $";

// 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'.

	@see Pooled
* /

class Pool {
public:

	Pool(void *astorage);

	//{@ statistics
	size_t total_allocated() { return ftotal_allocated; }
	unsigned int total_times() { return ftotal_times; }
	//}@

	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) {
		return check(real_calloc(size), size);
	}

	/// registers a routine to clean up non-pooled allocations
	void register_cleanup(void (*cleanup) (void *), void *data) {
		if(!real_register_cleanup(cleanup, data))
			fail_register_cleanup();
	}

	//{@ 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;
	}
	/// throws allocation exception
	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);
	}

	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		
			); 
	}

#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);
	}

};

/** 
	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;
		}
	}
};


template<typename T> class object_ptr {
	T *ptr;
public:
	typedef T element_type;

	explicit object_ptr(T *ptr = 0) {
		this->ptr=ptr;
		if(ptr)
			ptr->ref();
	}
	object_ptr(const object_ptr<T>& src) {
		ptr=src.get();
		ptr->ref();
	}
   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;
	}
	// so one could object_ptr<const T> = object_ptr<T>
	operator object_ptr<const T>() const{
		return *this;
	}
	operator bool() const {
		return get()!=0;
	}
	operator !() const {
		return get()==0;
	}
};

#define DECLARE_OBJECT_PTR(name) \
	typedef object_ptr<name> name##Ptr

//	typedef object_ptr<name> name##Ptr; \
//	const object_ptr<name> name##PtrZero(0);

/// TEMPLATE CLASS smart_ptr, stolen from stl:auto_ptr
template<class T>
	class smart_ptr {
public:
	typedef T element_type;
	explicit smart_ptr(T *_P = 0)
		: _Owns(_P != 0), _Ptr(_P) {}
	smart_ptr(const smart_ptr<T>& _Y)
		: _Owns(_Y._Owns), _Ptr(_Y.release()) {}
	smart_ptr<T>& operator=(const smart_ptr<T>& _Y)
		{if (this != &_Y)
			{if (_Ptr != _Y.get())
				{if (_Owns)
					delete _Ptr;
				_Owns = _Y._Owns; }
			else if (_Y._Owns)
				_Owns = true;
			_Ptr = _Y.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); }
	// so one could smart_ptr<const T> = smart_ptr<T>
	operator smart_ptr<const T>() const {
		return *this;
	}
	operator bool() const {
		return get()!=0;
	}
	operator T*() const {
		return _Ptr;
	}
private:
	bool _Owns;
	T *_Ptr;
	};

// convinient types

typedef smart_ptr<char> CharPtr;
const CharPtr CharPtrZero(0);

#endif

E-mail: