/* This file is part of libmemory, a library handling memory allocations
* more compfortable
* Copyright (C) 2004-2011 Niels Fröhling
*
* libmemory.hpp: global header
* Copyright 2004-2011 Niels Fröhling
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LIBMEMORY_HPP
#define LIBMEMORY_HPP
/* compiler specific pragmas */
#pragma warning (disable : 4996)
/* leak-detection */
#ifdef WIN32
#ifdef _DEBUG
#define _CRTDBG_MAPALLOC
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
#endif
/* system-definitions */
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <stddef.h>
/* integer for pointer storage */
typedef unsigned char memloc;
typedef uintptr_t pointer;
typedef uintptr_t ptrsize;
/* aligned allocations */
void *__stdcall mallocAligned(ptrsize size);
void *__stdcall callocAligned(ptrsize size);
void __stdcall freeAligned(void *ret);
#include "libmemory-0.0.0/Defines.hpp"
#include "libmemory-0.0.0/Memory.hpp"
#include "libmemory-0.0.0/MemoryHeader.hpp"
#include "libmemory-0.0.0/Pools.hpp"
#include "libmemory-0.0.0/Structures.hpp"
template<ptrsize alignment = AROS_WORSTALIGN>
class MemQueue : private MemPool<alignment> {
public:
MemQueue(const ptrsize blsize, const long int lmt) :
MemPool<alignment>(MEMF_ANY | MEMF_CLEAR, 512/*16384*/ * blsize, blsize) {
blocksize = blsize;
blocklimit = lmt;
head = NULL;
nums = 0;
allc = 0;
sizedsize = 0;
}
//~MemQueue() {
// printf("used %d bytes of memory (%d blocks of size %d, %d buffered)\n", getMemUsed(), blocksize, nums, allc);
//}
ptrsize blocksize;
ptrsize sizedsize;
long int blocklimit;
long int nums, allc;
protected:
struct MemBlock {
struct MemBlock *next;
} *head;
public:
/* receive a piece of memory the dimension given the initializer
* this type of allocation is maintained in a reusable cache
*/
inline void *obtainBlock() {
void *block;
if (!(block = head))
block = head = (struct MemBlock *)MemPool<alignment>::AllocPooled(blocksize);
else
allc--;
head = head->next;
nums++;
return block;
}
/* receive a piece of memory of custom dimension
* this type of allocation is uncached
*/
inline void *obtainBlock(ptrsize size) {
if (size > 0) {
sizedsize += size;
return MemPool<alignment>::AllocPooled(size);
}
return NULL;
}
/* receive multiple pieces of memory the dimension given the initializer
* this type of allocation is uncached
*/
inline void *obtainBlocks(long int num) {
sizedsize += blocksize * num;
return MemPool<alignment>::AllocPooled(blocksize * num);
}
/* giveaway a piece of memory the dimension given the initializer
* this type of allocation is maintained in a reusable cache
*/
inline void releaseBlock(void *block) {
struct MemBlock *mem = (struct MemBlock *)block;
mem->next = head;
head = mem;
nums--;
allc++;
}
/* giveaway a piece of memory of custom dimension
* this type of allocation is uncached
*/
inline void releaseBlock(void *block, ptrsize size) {
if (size > 0) {
sizedsize -= size;
MemPool<alignment>::FreePooled(block, size);
}
}
/* giveaway multiple pieces of memory the dimension given the initializer
* this type of allocation is uncached
*/
inline void releaseBlocks(void *block, long int num) {
sizedsize -= blocksize * num;
MemPool<alignment>::FreePooled(block, blocksize * num);
}
/* return the amount of memory actively in use, thus not in cache */
inline ptrsize getMemUsed() {
return blocksize * (nums) + sizedsize;
}
/* return the amount of memory taken from the system, thus also the cached */
inline ptrsize getMemAllocated() {
return blocksize * (nums + allc);
}
/* answer if the resource-limit has been reached, this is without effect on
* the allocator, but may be used for implementing memory-reuse algorithms
*/
inline bool reachedLimit() {
return (blocklimit < nums ? true : false);
}
};
class MemQueueable {
public:
/* **************************************************************************
*
* if order > lastbarrier
* use lastbarrier-memorypool
* if order > firstbarrier
* use firstbarrier-memorypool
* if order > basic
* use basic-memorypool
*
* use basic-memorypool[size];
*/
static void *operator new[] (size_t size, class MemQueue<4> *queue) {
return queue->obtainBlock(size);
}
static void operator delete[] (void *adr, size_t size, class MemQueue<4> *queue) {
queue->releaseBlock(adr, size);
}
static void operator delete[] (void *adr, class MemQueue<4> *queue) {
abort();
}
static void *operator new[] (size_t size) {
abort(); return malloc(size);
}
static void operator delete[] (void *adr, size_t size) {
abort(); free(adr);
}
static void operator delete[] (void *adr) {
abort(); free(adr);
}
static void *operator new(size_t size, class MemQueue<4> *queue) {
return queue->obtainBlock();
}
static void operator delete(void *adr, size_t size, class MemQueue<4> *queue) {
queue->releaseBlock(adr);
}
static void operator delete(void *adr, class MemQueue<4> *queue) {
queue->releaseBlock(adr);
}
static void *operator new(size_t size) {
return malloc(size);
}
static void operator delete(void *adr, size_t size) {
free(adr);
}
static void operator delete(void *adr) {
free(adr);
}
};
class MemAligned {
public:
static void *operator new[] (size_t size) {
return mallocAligned(size);
}
static void operator delete[] (void *adr, size_t size) {
freeAligned(adr);
}
static void operator delete[] (void *adr) {
freeAligned(adr);
}
static void *operator new(size_t size) {
return mallocAligned(size);
}
static void operator delete(void *adr, size_t size) {
freeAligned(adr);
}
static void operator delete(void *adr) {
freeAligned(adr);
}
};
#endif //LIBMEMORY_HPP