#ifndef AllocBuf_h
#define AllocBuf_h

#pragma interface

#include "assert_lkv.h"

extern "C" {
	#include <stddef.h>
	#include <stdlib.h>
}

class AllocBuf {

protected:

	static const int max_buf_size = 1024*256;

public:
		
	void ** pointer;
	unsigned long size;
	unsigned long pos;

	// only for debugging:
	unsigned long instance_cnt;
	const char * class_name;

	AllocBuf (unsigned long object_size, const char * cn) : pointer(0),
	       size(max_buf_size / object_size), pos(0), instance_cnt(0), class_name(cn) {

		if (size == 0) size++;
	
		pointer = new void * [size];
		assert (pointer != 0);
	};

	~AllocBuf (void) {

		assert(instance_cnt == 0);
		
		if (pointer) {
			for (unsigned long x = pos; x > 0; x--) {
				free( pointer[x-1] );
			}
			delete [] pointer;
		}
	};

};

#ifdef NO_LAZY_ALLOC

#define LAZYCLASS
#define LAZYCLASS_NONTEMPL
#define LAZYGETABUF(CLASS)
#define LAZYOPNEW(CLASS)
#define LAZYOPDEL(CLASS)
#define LAZYOPS(PREFIX,CLNAME)
#define LAZYOPS_NONTEMPL(CLNAME)
#define LAZYSTATIC(CLNAME)

#else

#ifdef DEBUG
	#define ALLOCBUF_DEBUG_P ab.instance_cnt++;
	#define ALLOCBUF_DEBUG_VP if (v) ab.instance_cnt++;
	#define ALLOCBUF_DEBUG_M ab.instance_cnt--;
#else
	#define ALLOCBUF_DEBUG_P 
	#define ALLOCBUF_DEBUG_VP 
	#define ALLOCBUF_DEBUG_M 
#endif
 
#define LAZYCLASS \
private: \
	static AllocBuf & get_alloc_buf(void); \
public: \
	void * operator new    (size_t size); \
	void   operator delete (void * p, size_t size); \
private:

#define LAZYCLASS_NONTEMPL \
private: \
	static AllocBuf ab_static; \
	static inline AllocBuf & get_alloc_buf(void) { return ab_static; }; \
public: \
	void * operator new    (size_t size); \
	void   operator delete (void * p, size_t size); \
private:

#define LAZYGETABUF(CLASS) \
inline AllocBuf & CLASS::get_alloc_buf (void) { \
	static AllocBuf ab(sizeof(CLASS), #CLASS ); \
	return ab; \
}

#define LAZYOPNEW(CLASS) \
inline void * CLASS::operator new (size_t size) { \
	if (size != sizeof(CLASS)) return (void *) malloc(size); \
	AllocBuf & ab(get_alloc_buf()); \
	if (ab.pos == 0) { \
		void * v = malloc(size); \
ALLOCBUF_DEBUG_VP \
		return v; \
	} \
ALLOCBUF_DEBUG_P \
	ab.pos--; \
	return ab.pointer[ab.pos]; \
}
	
#define LAZYOPDEL(CLASS) \
inline void CLASS::operator delete (void * p, size_t size) { \
	if (size != sizeof(CLASS)) { \
		free(p); \
		return; \
	} \
	AllocBuf & ab(get_alloc_buf()); \
ALLOCBUF_DEBUG_M \
	if (ab.pos >= ab.size) { \
		free (p); \
		return; \
	} \
	ab.pointer[ab.pos] = p; \
	ab.pos++; \
}

#define LAZYOPS(PREFIX,CLNAME) \
PREFIX \
LAZYGETABUF(CLNAME) \
PREFIX \
LAZYOPNEW(CLNAME) \
PREFIX \
LAZYOPDEL(CLNAME)

#define LAZYOPS_NONTEMPL(CLNAME) \
LAZYOPNEW(CLNAME) \
LAZYOPDEL(CLNAME)

#define LAZYSTATIC(CLNAME) \
AllocBuf CLNAME::ab_static(sizeof(CLNAME),#CLNAME);

#endif /* NO_LAZY_ALLOC */

#endif /* AllocBuf_h */


syntax highlighted by Code2HTML, v. 0.9.1