#ifndef CPP_EXEC_MEMORY_H
#define CPP_EXEC_MEMORY_H

// Klassen zum Umgang mit dem Heap, Systemspeicher und Memorypools
//
// Autor: Jochen Becher
//
// Historie:
//
// Version 1.0 am 25. Juni 94

#ifndef _INCLUDE_STDDEF_H
#include <stddef.h>
#endif

#ifndef EXEC_MEMORY_H
#include <exec/memory.h>
#endif

#ifndef CPP_EXEC_LISTS_H
#include <classes/exec/lists.h>
#endif

#ifndef CPP_EXEC_SHARE_H
#include <classes/exec/share.h>
#endif

#ifndef CPP_DATASTRUCTURES_GENARRAYLIST_H
#include <classes/datastructures/genarraylist.h>
#endif

class PoolListC : public ListC {
public:
	PoolListC();
	~PoolListC();
};

class PublicHeapC {
public:
	static void *operator new(size_t bytes);
	static void operator delete(void *object, size_t bytes);
private:
	static PoolListC pool;
};

// ******************************************************************

class MemoryC : protected ShareManualC {
public:
	MemoryC() throw (MemoryX);
	MemoryC(const MemoryC &);
	~MemoryC();
	APTR memory() const { return mMemory; };
	ULONG size() const { return mSize; };
	MemoryC &operator= (const MemoryC &);
	APTR allocate(ULONG bytes, ULONG flags = MEMF_ANY) throw (MemoryX);
	VOID free();
	ULONG available(ULONG flags = MEMF_ANY);
private:
	APTR mMemory;
	ULONG mSize;
};

class ChipMemoryC : public MemoryC {
public:
	ChipMemoryC() throw (MemoryX)
		: MemoryC() { };
	APTR allocate(ULONG bytes, ULONG flags = MEMF_ANY) throw (MemoryX)
		{ return MemoryC::allocate(bytes,MEMF_CHIP|flags); };
	ULONG available(ULONG flags = MEMF_ANY)
		{ return MemoryC::available(MEMF_CHIP|flags); };
};

class PublicMemoryC : public MemoryC {
public:
	PublicMemoryC() throw (MemoryX)
		: MemoryC() { };
	APTR allocate(ULONG bytes, ULONG flags = MEMF_ANY) throw (MemoryX)
		{ return MemoryC::allocate(bytes,MEMF_PUBLIC|flags); };
	ULONG available(ULONG flags = MEMF_ANY)
		{ return MemoryC::available(MEMF_PUBLIC|flags); };
};

class PublicChipMemoryC : public MemoryC {
public:
	PublicChipMemoryC() throw (MemoryX)
		: MemoryC() { };
	APTR allocate(ULONG bytes, ULONG flags = MEMF_ANY) throw (MemoryX)
		{ return MemoryC::allocate(bytes,MEMF_PUBLIC|MEMF_CHIP|flags); };
	ULONG available(ULONG flags = MEMF_ANY)
		{ return MemoryC::available(MEMF_PUBLIC|MEMF_CHIP|flags); };
};

// ******************************************************************

class MemoryPoolC : protected ListC {
public:
	MemoryPoolC(ULONG flags = MEMF_ANY, ULONG poolsize = 65536);
	~MemoryPoolC();
	VOID changePoolsize(ULONG poolsize);
	APTR allocate(ULONG bytes) throw (MemoryX);
	VOID free(APTR address, ULONG bytes);
private:
	ULONG mflags;
	ULONG psize;
};

// *************************************************************

struct SmallMemoryBlock {
	APTR memory;
	ULONG size;
	ULONG full;
};

class SmallMemoryPoolC {
public:
	SmallMemoryPoolC(ULONG flags = MEMF_ANY, ULONG poolsize = 16384) throw (MemoryX);
	~SmallMemoryPoolC();
	APTR allocate(ULONG bytes) throw (MemoryX);
	VOID free(APTR address, ULONG bytes);
	VOID flush() throw (MemoryX);
private:
	gen_arraylist pools;
	struct SmallMemoryBlock *pool;
	ULONG mflags;
	ULONG psize;
};

#endif
