Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

swh:1:snp:c78d7a14cc07423acb6a43d0e3059b9afd67996a
  • Code
  • Branches (1)
  • Releases (0)
    • Branches
    • Releases
    • HEAD
    • refs/heads/master
    No releases to show
  • f9aac5f
  • /
  • src
  • /
  • memPool.h
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
  • revision
  • snapshot
content badge
swh:1:cnt:0a725b4d1ffbd97ca2d4d180f3c2191e5674b8fa
directory badge
swh:1:dir:4f575ba51229ed8a439e690987eb7223782b67ec
revision badge
swh:1:rev:c5be799ee3dad53f5edf10eeb39527bbca5add11
snapshot badge
swh:1:snp:c78d7a14cc07423acb6a43d0e3059b9afd67996a

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
  • revision
  • snapshot
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Tip revision: c5be799ee3dad53f5edf10eeb39527bbca5add11 authored by LorenzoDiazzi on 29 May 2025, 10:15:58 UTC
Update README.md
Tip revision: c5be799
memPool.h
/****************************************************************************
* NFG - Numbers for Geometry                     					        *
*                                                                           *
* Consiglio Nazionale delle Ricerche                                        *
* Istituto di Matematica Applicata e Tecnologie Informatiche                *
* Sezione di Genova                                                         *
* IMATI-GE / CNR                                                            *
*                                                                           *
* Authors: Marco Attene                                                     *
* Copyright(C) 2019: IMATI-GE / CNR                                         *
* All rights reserved.                                                      *
*                                                                           *
* This program is free software; you can redistribute it and/or modify      *
* it under the terms of the GNU Lesser General Public License as published  *
* by the Free Software Foundation; either version 3 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 Lesser  *
* General Public License for more details.                                  *
*                                                                           *
* You should have received a copy of the GNU Lesser General Public License  *
* along with this program.  If not, see http://www.gnu.org/licenses/.       *
*                                                                           *
****************************************************************************/

#ifndef MEMPOOL_H
#define MEMPOOL_H

#include <vector>
#include <bit>
#include <bitset>
#include <cstdint>

// An N_block is a contiguous portion of memory elements.
// An N_memory_pool stores a set of N_blocks along with
// a 'stack' of pointers to these blocks.
// Upon allocation, the first free block is picked from the stack.
// If the stack is empty, the size of the pool (and the stack) is grown.
// When a block is released, its pointer is added on top of the stack.
//
// alloc is almost always O(1) [O(num_blocks) only if growth is required]
// release is always O(1)

class N_memory_pool {
	std::vector<uint8_t*> data; // Data storage. Each data[i] is an array of N_blocks
	uint8_t** stack;	// Stack of pointers to free blocks
	size_t last;		// Element past to the last in the stack
	size_t size;		// Size of the pool (total number of blocks)
	const size_t block_size; // Size of one block (number N of elements)

	void addDataBlockArray(size_t tot_size, uint8_t** fs) {
		uint8_t* data_1 = (uint8_t*)malloc(sizeof(uint8_t)*tot_size);
		data.push_back(data_1);
		uint8_t* lst = data_1 + tot_size;
		while (lst != data_1) {
			lst -= block_size;
			*fs++ = lst;
		}
	}

	void doubleDataArray() {
		uint8_t** fs = (uint8_t**)malloc(sizeof(uint8_t *) * size * 2);
		size_t i = 0, j = size;
		while (i < size) fs[j++] = stack[i++];
		free(stack);
		stack = fs;

		addDataBlockArray(block_size * size, fs);

		last += size;
		size *= 2;
	}

public:
	N_memory_pool(size_t _size, size_t _block_size) : last(_size), size(_size), block_size(_block_size) {
		stack = (uint8_t**)malloc(sizeof(uint8_t*) * size);
		uint8_t** fs = stack;
		addDataBlockArray(size * block_size, fs);
	}

	N_memory_pool(N_memory_pool&& p) noexcept;

	~N_memory_pool() {
		free(stack);
		for (uint8_t* p : data) free(p);
		data.clear();
	}

	void* alloc() {
		if (last == 0) doubleDataArray();
		return stack[--last];
	}

	void release(void* s) {	stack[last++] = (uint8_t *)s; }
};

inline N_memory_pool::N_memory_pool(N_memory_pool&& p) noexcept
	: data(p.data), stack(p.stack), last(p.last), size(p.size), block_size(p.block_size) {
	p.stack = nullptr;
	p.data.clear();
}

// An N_block is a contiguous portion of 32-bit memory elements.
// An extended_N_block is the concatentaion of [N] and an N_block.
//
//		i.e. uint32_t block_N[N+1] = { N, v1, v2, ..., vN };
// 
// An Indexed N pool (IN_pool) stores a set of extended_N_blocks along with
// a 'stack' of pointers to these extended blocks. Each pointer in the stack
// points to the second element of an extended block because the first must 
// always store the block size and is therefore reserved.
// Upon allocation, the first free block is picked from the stack.
// If the stack is empty, the size of the pool (and the stack) is grown.
// When a block is released, its pointer is added on top of the stack.
//
// alloc is almost always O(1) [O(num_blocks) only if growth is required]
// release is always O(1)

class IN_pool {
	std::vector<uint32_t*> data; // Data storage. Each data[i] is an array of extended_N_blocks
	uint32_t** stack;	// Stack of pointers to free blocks
	uint32_t last;		// Element past to the last in the stack
	uint32_t size;		// Size of the pool (total number of blocks)
	const uint32_t block_size; // Size of one block (number N of elements)

	void addDataBlockArray(uint32_t tot_size, uint32_t extended_block_size, uint32_t** fs) {
		uint32_t* data_1 = (uint32_t*)malloc(sizeof(uint32_t) * tot_size);
		data.push_back(data_1);
		uint32_t* lst = data_1 + tot_size;
		while (lst != data_1) {
			lst -= extended_block_size;
			*lst = block_size;
			*fs++ = lst + 1;
		}
	}

	void doubleDataArray() {
		const uint32_t extended_block_size = block_size + 1;

		uint32_t** fs = (uint32_t**)malloc(sizeof(uint32_t*) * size * 2);
		for (uint32_t i = 0; i < size; i++) fs[i + size] = stack[i];
		free(stack);
		stack = fs;

		addDataBlockArray(extended_block_size * size, extended_block_size, fs);

		last += size;
		size *= 2;
	}

public:
	IN_pool(uint32_t _size, uint32_t _block_size) : last(_size), size(_size), block_size(_block_size) {
		const uint32_t extended_block_size = block_size + 1;
		stack = (uint32_t**)malloc(sizeof(uint32_t*) * size);
		uint32_t** fs = stack;
		addDataBlockArray(size * extended_block_size, extended_block_size, fs);
	}

	IN_pool(IN_pool&& p) noexcept;

	~IN_pool() {
		free(stack);
		for (uint32_t* p : data) free(p);
		data.clear();
	}

	uint32_t* alloc() {
		if (last == 0) doubleDataArray();
		return stack[--last];
	}

	void release(uint32_t* s) { stack[last++] = s; }

	uint32_t blockSize() const { return block_size; }
};

inline IN_pool::IN_pool(IN_pool&& p) noexcept
	: data(p.data), stack(p.stack), last(p.last), size(p.size), block_size(p.block_size) {
	p.stack = nullptr;
	p.data.clear();
}

// A MultiPool is a collection of IN_pools having size N = 2, 4, 8, 16, ..., 2^m
// 
// Upon allocation for X elements two cases may occur:
// 1) X <= 2^m
//     Calculate the minimum value of N such that N >= X
//     Allocate a block in the corresponding IN_pool
// 2) X > 2^m 
//	   standard malloc() is used for X+1 elements
// 	   first element is set to 0 [meaning that no IN_pool was used]
// 	   a pointer to the second element is returned for use
//
// Upon release of a pointer A
//    Let V be the value of the element preceeding the one pointed by A (i.e. V = A[-1])
//    If V==0 use standard free()
//    else if V==N release a block is the corresponding IN_pool

class MultiPool {
	std::vector<IN_pool> IN_pools;
	uint32_t max_block_size;

	IN_pool& pickPoolFromSize(uint32_t bs) {
		auto cz = std::countl_zero(bs - 1);
		cz = (cz == 32) ? (31) : (cz);
		return IN_pools[31 - cz];

		//// FOR COMPILERS THAT DO NOT SUPPORT C++20 REPLACE THE ABOVE WITH THE FOLLOWING
		//std::vector<IN_pool>::iterator i = IN_pools.begin();
		//while ((*i).blockSize() < bs) i++;
		//return *i;
	}

public:
	MultiPool(uint32_t _max_block_size = 32, uint32_t init_capacity = 16) : max_block_size(_max_block_size) {
		uint32_t bs = 1;
		while (bs < max_block_size) {
			bs <<= 1;
			IN_pools.push_back(IN_pool(init_capacity, bs));
		}
	}

	void* alloc(uint32_t num_bytes) {
		const uint32_t num_els = ((num_bytes + 3) >> 2);
		if (num_els > max_block_size) {
			uint32_t* ptr;
			if ((ptr = (uint32_t*)malloc(sizeof(uint32_t) * (num_els + 1))) == NULL) return NULL;
			ptr[0] = 0;
			return ptr + 1;
		}

		return pickPoolFromSize(num_els).alloc();
	}

	void release(void* s) {
		if (s) {
			uint32_t* ps = (((uint32_t*)s) - 1);
			const uint32_t v = *ps;
			if (v == 0) {
				free(ps);
				return;
			}

			pickPoolFromSize(v).release(((uint32_t*)s));
		}
	}
};

#endif //MEMPOOL_H

back to top

Software Heritage — Copyright (C) 2015–2025, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API