<commit_before>/*
 * Copyright (c) 2005, <NAME> and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "PoolAllocator.h"

//--- standard modules used ----------------------------------------------------
#include "ITOString.h"
#include "MemHeader.h"
#include "SysLog.h"

//--- c-library modules used ---------------------------------------------------
#include <stdlib.h>

#if !defined(__SUNPRO_CC) ||  __SUNPRO_CC < 0x500
extern void *operator new(size_t size, void *vp);
#if defined(WIN32) && (_MSC_VER >= 1200) // VC6 or greater
extern void operator delete(void *ptr, void *vp);
#endif
extern void operator delete(void *ptr);
#endif

//---- PoolAllocator ------------------------------------------
struct PoolBucket {
	u_long fSize;
	u_long fUsableSize;
	void *fFirstFree;
};

PoolAllocator::PoolAllocator(long poolid, u_long poolSize, u_long maxPoolBuckets)
	: Allocator(poolid)
	, fNumOfPoolBucketSizes(maxPoolBuckets)
	MemTrackInit(fPoolTracker)
	MemTrackInit(fExcessTracker)
{
	fAllocSz = poolSize * 1024;
	fPoolMemory = ::calloc(fAllocSz, 1);
	fPoolBuckets = (PoolBucket *)::calloc(fNumOfPoolBucketSizes + 1, sizeof(PoolBucket));

	if (!fPoolMemory || !fPoolBuckets) {
		static const char crashmsg[] = "FATAL: PoolAllocator::PoolAllocator calloc failed. I will crash :-(\n";
		SysLog::WriteToStderr(crashmsg, sizeof(crashmsg));

		// We might never see the following because we have no memory.
		String msg("PoolAllocator: ");
		msg << "allocation of PoolStorage: " << (long)poolSize << ", " << (long)maxPoolBuckets << " failed";
		SysLog::Error(msg);
		Unref(); // signal allocation failure
		return;
	}
	Initialize();

#ifdef MEM_DEBUG
	fPoolTracker.SetId(poolid);
	fExcessTracker.SetId(poolid);
#endif
}

long PoolAllocator::SetId(long lId)
{
#ifdef MEM_DEBUG
	fPoolTracker.SetId(lId);
	fExcessTracker.SetId(lId);
#endif
	return Allocator::SetId(lId);
}

void PoolAllocator::Initialize()
{
	// initialize data structures used by the allocator
	long sz = 16;

	for (long i = 0; i < (long)fNumOfPoolBucketSizes; i++) {
		fPoolBuckets[i].fSize = sz;
		fPoolBuckets[i].fUsableSize = sz - MemoryHeader::AlignedSize();	// optimization
		fPoolBuckets[i].fFirstFree = NULL;

		sz *= 2;
	}
	fPoolBuckets[fNumOfPoolBucketSizes].fSize = 0;
	fPoolBuckets[fNumOfPoolBucketSizes].fFirstFree = ((char *)fPoolMemory) + fAllocSz;
}

PoolAllocator::~PoolAllocator()
{
#ifdef MEM_DEBUG
	{
		MemTrackStat(fPoolTracker);
	} {
		// caution: must use scoping because tracking would increase fPoolTrackers allocated count!
		MemTrackStat(fExcessTracker);
	}
	if (fPoolTracker.CurrentlyAllocated() != 0) {
		SysLog::Error(String("deleted PoolAllocator [") << GetId() << "] " << (long)this << " was still in use!");
	}
#endif
	::free(fPoolBuckets);
	::free(fPoolMemory);
}

void PoolAllocator::Free(void *vp)
{
	MemoryHeader *header = RealMemStart(vp);

	if ( header ) {
		if (header->fState == MemoryHeader::eUsed ) {	// most likely case first
			// recycle into pool
			PoolBucket *bucket = FindBucketBySize( header->fSize + MemoryHeader::AlignedSize());

			if ( bucket ) {
				Assert(header->fSize + MemoryHeader::AlignedSize() == bucket->fSize);

				MemTrackFree(fPoolTracker, header->fSize);
				InsertFreeHeaderIntoBucket(header, bucket);<commit_msg>using new MemTrack macros for printing statistics<commit_after>/*
 * Copyright (c) 2005, <NAME> and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "PoolAllocator.h"

//--- standard modules used ----------------------------------------------------
#include "ITOString.h"
#include "MemHeader.h"
#include "SysLog.h"

//--- c-library modules used ---------------------------------------------------
#include <stdlib.h>

#if !defined(__SUNPRO_CC) ||  __SUNPRO_CC < 0x500
extern void *operator new(size_t size, void *vp);
#if defined(WIN32) && (_MSC_VER >= 1200) // VC6 or greater
extern void operator delete(void *ptr, void *vp);
#endif
extern void operator delete(void *ptr);
#endif

//---- PoolAllocator ------------------------------------------
struct PoolBucket {
	u_long fSize;
	u_long fUsableSize;
	void *fFirstFree;
};

PoolAllocator::PoolAllocator(long poolid, u_long poolSize, u_long maxPoolBuckets)
	: Allocator(poolid)
	, fNumOfPoolBucketSizes(maxPoolBuckets)
	MemTrackInit(fPoolTracker)
	MemTrackInit(fExcessTracker)
{
	fAllocSz = poolSize * 1024;
	fPoolMemory = ::calloc(fAllocSz, 1);
	fPoolBuckets = (PoolBucket *)::calloc(fNumOfPoolBucketSizes + 1, sizeof(PoolBucket));

	if (!fPoolMemory || !fPoolBuckets) {
		static const char crashmsg[] = "FATAL: PoolAllocator::PoolAllocator calloc failed. I will crash :-(\n";
		SysLog::WriteToStderr(crashmsg, sizeof(crashmsg));

		// We might never see the following because we have no memory.
		String msg("PoolAllocator: ");
		msg << "allocation of PoolStorage: " << (long)poolSize << ", " << (long)maxPoolBuckets << " failed";
		SysLog::Error(msg);
		Unref(); // signal allocation failure
		return;
	}
	Initialize();

#ifdef MEM_DEBUG
	fPoolTracker.SetId(poolid);
	fExcessTracker.SetId(poolid);
#endif
}

long PoolAllocator::SetId(long lId)
{
#ifdef MEM_DEBUG
	fPoolTracker.SetId(lId);
	fExcessTracker.SetId(lId);
#endif
	return Allocator::SetId(lId);
}

void PoolAllocator::Initialize()
{
	// initialize data structures used by the allocator
	long sz = 16;

	for (long i = 0; i < (long)fNumOfPoolBucketSizes; i++) {
		fPoolBuckets[i].fSize = sz;
		fPoolBuckets[i].fUsableSize = sz - MemoryHeader::AlignedSize();	// optimization
		fPoolBuckets[i].fFirstFree = NULL;

		sz *= 2;
	}
	fPoolBuckets[fNumOfPoolBucketSizes].fSize = 0;
	fPoolBuckets[fNumOfPoolBucketSizes].fFirstFree = ((char *)fPoolMemory) + fAllocSz;
}

PoolAllocator::~PoolAllocator()
{
	MemTrackStatIfAllocated(fPoolTracker);
	MemTrackStatIfAllocated(fExcessTracker);
	MemTrackStillAllocatedException(fPoolTracker);
	::free(fPoolBuckets);
	::free(fPoolMemory);
}

void PoolAllocator::Free(void *vp)
{
	MemoryHeader *header = RealMemStart(vp);

	if ( header ) {
		if (header->fState == MemoryHeader::eUsed ) {	// most likely case first
			// recycle into pool
			PoolBucket *bucket = FindBucketBySize( header->fSize + MemoryHeader::AlignedSize());

			if ( bucket ) {
				Assert(header->fSize + MemoryHeader::AlignedSize() == bucket->fSize);

				MemTrackFree(fPoolTracker, header->fSize);
				InsertFreeHeaderIntoBucket(header, bucket);
{'fraction_non_alphanumeric': 0.18333813779187086, 'fraction_numerical': 0.007639089074661286, 'mean_word_length': 3.682186234817814, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '345393', 'n_tokens_mistral': 2379, 'n_tokens_neox': 2224, 'n_words': 541}