<commit_before>/*************************************************************************/
/* Copyright (c) 2018 <NAME>                                     */
/* All rights reserved                                                   */
/*                                                                       */
/* Use of the link grammar parsing system is subject to the terms of the */
/* license set forth in the LICENSE file included with this software.    */
/* This license allows free redistribution and use in source and binary  */
/* forms, with or without modification, subject to certain conditions.   */
/*                                                                       */
/*************************************************************************/

#ifndef _MEMORY_POOL_H
#define _MEMORY_POOL_H

#include "link-includes.h"
#include "error.h"
#include "utilities.h"                  // GNUC_MALLOC (XXX separate include?)

#define D_MEMPOOL (D_SPEC+4)
#define MIN_ALIGNMENT sizeof(void *)    // Minimum element alignment.
#define MAX_ALIGNMENT 64                // Maximum element alignment.
//#define POOL_FREE                       // Allow to reuse individual elements.
/*#define POOL_EXACT // Not used for now and hence left undefined. */

typedef struct Pool_desc_s Pool_desc;

Pool_desc *pool_new(const char *, const char *, size_t, size_t, bool, bool, bool);
void *pool_alloc_vec(Pool_desc *, size_t) GNUC_MALLOC;

void pool_reuse(Pool_desc *);
#ifndef DEBUG
void pool_delete(Pool_desc *);
#else
void pool_delete(const char *func, Pool_desc *);
#define pool_delete(...) pool_delete (__func__, __VA_ARGS__)
#endif
#ifdef POOL_FREE
void pool_free(Pool_desc *, void *e);
#endif // POOL_FREE

/* Pool allocator debug facility:
 * If configured with "CPPFLAGS=-DPOOL_ALLOCATOR=0", a fake pool allocator
 * that uses malloc() for each allocation is defined, in order that ASAN
 * or valgrind can be used to find memory usage bugs.
 */

#ifndef POOL_ALLOCATOR
#define POOL_ALLOCATOR 1
#endif

#define FLDSIZE_NEXT sizeof(char *) // "next block" field size
#define POOL_NEXT_BLOCK(blk, offset_next) (*(char **)((blk)+(offset_next)))

struct  Pool_desc_s
{
	/* Used only by the real pool allocator. */
	char *ring;                 // Current area for allocation.
	char *alloc_next;           // Next element to be allocated.
#ifdef POOL_FREE
	char *free_list;            // Allocations that got freed.
#endif // POOL_FREE
	size_t block_size;          // Block size for pool extension.
	size_t data_size;           // Size of data inside block_size.
	size_t alignment;           // Alignment of element allocation.
	size_t num_elements;        // Number of elements per block.

	/* Common to the real and fake pool allocators. */
	char *chain;                // Allocated blocks.
	size_t element_size;        // Allocated memory per element.
	const char *name;           // Pool name.
	const char *func;           // Invoker of pool_new().
	/* num_elements is also used by the fake allocator if the POOL_EXACT
	 * feature is used (it is not used for now). */

	size_t curr_elements;       // Originally for debug. Now used by pool_next().

	/* Flags that are used by pool_alloc(). */
	bool zero_out;              // Zero out allocated elements.
#ifdef POOL_EXACT
	bool exact;                 // Abort if more than num_elements are needed.
#endif /* POOL_EXACT */
};

typedef struct
{
	char *current_element;
	char *block_end;
	size_t element_number;
} Pool_location;

static inline void *pool_alloc(Pool_desc *mp)
{
	return pool_alloc_vec(mp, 1);
}

/**
 * Return the next element in the pool.
 * @param Pool_location Iteration state. Should be initialized to 0
 * before starting the iteration.
 * @return A different element on each call, \c NULL when there are no more.
 */
static inline void *pool_next(Pool_desc *mp, Pool_location *l)
{
#ifdef POOL_FREE
	assert(mp->free_list == NULL, "Cannot be called after pool_free()");
#endif

	if (l->element_number == mp->curr_elements) return NULL;

	if (l->element_number == 0)
	{
		/* This is an initial request for pool traversal.
		 * Initialize the location descriptor and return the first element. */
		l->element_number = 1;
		l->current_element = mp->chain;
#ifdef POOL_ALLOCATOR
		l->block_end = mp->chain + mp->data_size;
#endif

		return l->current_element;
	}

#if POOL_ALLOCATOR
	l->current_element += mp->element_size;
	if (l->current_element == l->block_end)
	{<commit_msg>pool_next(): Fix the function comment<commit_after>/*************************************************************************/
/* Copyright (c) 2018 <NAME>                                     */
/* All rights reserved                                                   */
/*                                                                       */
/* Use of the link grammar parsing system is subject to the terms of the */
/* license set forth in the LICENSE file included with this software.    */
/* This license allows free redistribution and use in source and binary  */
/* forms, with or without modification, subject to certain conditions.   */
/*                                                                       */
/*************************************************************************/

#ifndef _MEMORY_POOL_H
#define _MEMORY_POOL_H

#include "link-includes.h"
#include "error.h"
#include "utilities.h"                  // GNUC_MALLOC (XXX separate include?)

#define D_MEMPOOL (D_SPEC+4)
#define MIN_ALIGNMENT sizeof(void *)    // Minimum element alignment.
#define MAX_ALIGNMENT 64                // Maximum element alignment.
//#define POOL_FREE                       // Allow to reuse individual elements.
/*#define POOL_EXACT // Not used for now and hence left undefined. */

typedef struct Pool_desc_s Pool_desc;

Pool_desc *pool_new(const char *, const char *, size_t, size_t, bool, bool, bool);
void *pool_alloc_vec(Pool_desc *, size_t) GNUC_MALLOC;

void pool_reuse(Pool_desc *);
#ifndef DEBUG
void pool_delete(Pool_desc *);
#else
void pool_delete(const char *func, Pool_desc *);
#define pool_delete(...) pool_delete (__func__, __VA_ARGS__)
#endif
#ifdef POOL_FREE
void pool_free(Pool_desc *, void *e);
#endif // POOL_FREE

/* Pool allocator debug facility:
 * If configured with "CPPFLAGS=-DPOOL_ALLOCATOR=0", a fake pool allocator
 * that uses malloc() for each allocation is defined, in order that ASAN
 * or valgrind can be used to find memory usage bugs.
 */

#ifndef POOL_ALLOCATOR
#define POOL_ALLOCATOR 1
#endif

#define FLDSIZE_NEXT sizeof(char *) // "next block" field size
#define POOL_NEXT_BLOCK(blk, offset_next) (*(char **)((blk)+(offset_next)))

struct  Pool_desc_s
{
	/* Used only by the real pool allocator. */
	char *ring;                 // Current area for allocation.
	char *alloc_next;           // Next element to be allocated.
#ifdef POOL_FREE
	char *free_list;            // Allocations that got freed.
#endif // POOL_FREE
	size_t block_size;          // Block size for pool extension.
	size_t data_size;           // Size of data inside block_size.
	size_t alignment;           // Alignment of element allocation.
	size_t num_elements;        // Number of elements per block.

	/* Common to the real and fake pool allocators. */
	char *chain;                // Allocated blocks.
	size_t element_size;        // Allocated memory per element.
	const char *name;           // Pool name.
	const char *func;           // Invoker of pool_new().
	/* num_elements is also used by the fake allocator if the POOL_EXACT
	 * feature is used (it is not used for now). */

	size_t curr_elements;       // Originally for debug. Now used by pool_next().

	/* Flags that are used by pool_alloc(). */
	bool zero_out;              // Zero out allocated elements.
#ifdef POOL_EXACT
	bool exact;                 // Abort if more than num_elements are needed.
#endif /* POOL_EXACT */
};

typedef struct
{
	char *current_element;
	char *block_end;
	size_t element_number;
} Pool_location;

static inline void *pool_alloc(Pool_desc *mp)
{
	return pool_alloc_vec(mp, 1);
}

/**
 * Return the next element in the pool, starting with the first one.
 * @param l Iteration state. \c *l should be initialized to
 * (Pool_location)0 before starting the iteration.
 * @return The next element on each call, \c NULL when there are no
 * more.
 */
static inline void *pool_next(Pool_desc *mp, Pool_location *l)
{
#ifdef POOL_FREE
	assert(mp->free_list == NULL, "Cannot be called after pool_free()");
#endif

	if (l->element_number == mp->curr_elements) return NULL;

	if (l->element_number == 0)
	{
		/* This is an initial request for pool traversal.
		 * Initialize the location descriptor and return the first element. */
		l->element_number = 1;
		l->current_element = mp->chain;
#ifdef POOL_ALLOCATOR
		l->block_end = mp->chain + mp->data_size;
#endif

		return l->current_element;
	}

#if POOL_ALLOCATOR
	l->current_element += mp->element_size;
	if (l->current_element == l->block_end)
	{
{'fraction_non_alphanumeric': 0.12823660714285715, 'fraction_numerical': 0.0029017857142857144, 'mean_word_length': 2.725987525987526, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7628782', 'n_tokens_mistral': 2618, 'n_tokens_neox': 2506, 'n_words': 911}