/* Copyright 2007, 2008 Daniel Zerbino (zerbino@ebi.ac.uk) This file is part of Velvet. Velvet 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. Velvet 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 Velvet; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /****************************************************************\ * * * Efficient Memory Allocation Routines * * * * Guy St.C. Slater.. mailto:guy@ebi.ac.uk * * Copyright (C) 2000-2005. All Rights Reserved. * * * * This source code is distributed under the terms of the * * GNU Lesser General Public License. See the file COPYING * * or http://www.fsf.org/copyleft/lesser.html for details * * * * If you use this code, please keep this notice intact. * * * \****************************************************************/ #include #include #include "globals.h" #include "recycleBin.h" #include "utility.h" typedef struct RecycleBin_Node { struct RecycleBin_Node *next; } RecycleBin_Node; typedef struct chunk_st { struct chunk_st *next; } Chunk; struct recycleBin_st { Chunk *chunk_list; RecycleBin_Node *recycle; size_t node_size; int chunk_pos; int nodes_per_chunk; }; static void initRecycleBin(RecycleBin *recycleBin, size_t node_size, int nodes_per_chunk) { size_t chunckSize, allocSize; chunckSize = sizeof(Chunk) + nodes_per_chunk * node_size; allocSize = 1; /* Get nearest power of 2 */ while (allocSize < chunckSize) allocSize <<= 1; nodes_per_chunk = (allocSize - sizeof(Chunk)) / node_size; recycleBin->chunk_list = NULL; recycleBin->chunk_pos = nodes_per_chunk; recycleBin->nodes_per_chunk = nodes_per_chunk; recycleBin->node_size = node_size; recycleBin->recycle = NULL; } RecycleBin *newRecycleBin(size_t node_size, int nodes_per_chunk) { RecycleBin *recycleBin; if (node_size < sizeof(RecycleBin_Node)) { velvetLog("Too small elements to create a recycle bin!\n"); #ifdef DEBUG abort(); #endif exit(-1); } recycleBin = mallocOrExit(1, RecycleBin); initRecycleBin (recycleBin, node_size, nodes_per_chunk); return recycleBin; } static void destroyRecycleBinChunks(RecycleBin * recycleBin) { while (recycleBin->chunk_list != NULL) { Chunk *chunk; chunk = recycleBin->chunk_list; recycleBin->chunk_list = recycleBin->chunk_list->next; free(chunk); } } void destroyRecycleBin(RecycleBin * recycleBin) { if (recycleBin == NULL) return; destroyRecycleBinChunks(recycleBin); free(recycleBin); } void *allocatePointer(RecycleBin * recycle_bin) { RecycleBin_Node *node; Chunk *chunk; if (recycle_bin == NULL) { velvetLog("Null recycle bin!\n"); #ifdef DEBUG abort(); #endif exit(-1); } if (recycle_bin->recycle != NULL) { node = recycle_bin->recycle; recycle_bin->recycle = node->next; return node; } if (recycle_bin->chunk_pos == recycle_bin->nodes_per_chunk) { chunk = malloc(sizeof(Chunk) + recycle_bin->nodes_per_chunk * recycle_bin->node_size); if (chunk == NULL) { velvetLog("No more memory for memory chunk!\n"); #ifdef DEBUG abort(); #endif exit(-1); } chunk->next = recycle_bin->chunk_list; recycle_bin->chunk_list = chunk; recycle_bin->chunk_pos = 1; return (RecycleBin_Node *) ((size_t) (void *) chunk + sizeof(Chunk)); } chunk = recycle_bin->chunk_list; return (RecycleBin_Node *) ((size_t) (void *) chunk + sizeof(Chunk) + (recycle_bin-> node_size * recycle_bin->chunk_pos++)); } void deallocatePointer(RecycleBin * recycle_bin, void *data) { RecycleBin_Node *node = data; node->next = recycle_bin->recycle; recycle_bin->recycle = node; return; } #ifdef _OPENMP RecycleBin *newRecycleBinArray(unsigned int n, size_t node_size, int nodes_per_chunk) { RecycleBin *recycleBin; int i; recycleBin = mallocOrExit (n + 1, RecycleBin); for (i = 0; i < n; i++) initRecycleBin(recycleBin + i, node_size, nodes_per_chunk); /* Last element marker */ recycleBin[n].node_size = 0; return recycleBin; } void destroyRecycleBinArray(RecycleBin * recycleBin) { int i; for (i = 0; recycleBin[i].node_size != 0; i++) destroyRecycleBinChunks(recycleBin + i); free(recycleBin); } RecycleBin *getRecycleBinInArray(RecycleBin *recycleBin, int position) { return recycleBin + position; } #endif