blob: 51433dc55da5c5ea18001500b40211bcaefdfc70 [file] [log] [blame]
//Copyright 2009 Princeton University
//Written by Christian Bienia
/* This file contains methods and data structures to:
* - Allocate and manage memory buffers
* - Keep track of the usage of memory buffers and free them if necessary
* - Methods to break memory buffers into smaller buffers
* The purpose of all this is to eliminate memory copies by reusing allocated memory as much as possible
*
* Note on use in multithreaded programs:
* The routines expect that the caller takes care of guaranteeing exclusive access to the arguments
* passed to the routines. Access to meta data that might be shared between multiple arguments (and
* hence threads) will be synchronized. Obviously the user is responsible for synchronizing access
* to the contents of the buffers.
*
* Note on allocating and freeing:
* Two memory areas need to be distinguished: The mbuffer_t structure and the buffer that is encapsulated.
* The subsystem can be used with both statically and dynamically allocated mbuffer_t structures. It will
* always automatically free mbuffer_t structures it has allocated itself. Manually allocated mbuffer_t
* structuers also need to be freed manually. The memory for the encapsulated buffer is always freed
* automatically and needs to be dynamically allocated if manual allocation is used.
*/
#ifndef _MBUFFER_H_
#define _MBUFFER_H_
#include <stdlib.h>
//Add additional code to catch unallocated mbuffers and multiple frees
//#define ENABLE_MBUFFER_CHECK
#ifdef ENABLE_MBUFFER_CHECK
//random number to detect properly allocated & initialized mbuffers
#define MBUFFER_CHECK_MAGIC 4363097
#endif
//Definition of a memory control block (MCB) which tracks everything relevant for the correct use of malloc/free
//Dedup breaks memory buffers into smaller memory buffers during its operation, which means that free() cannot
//be called until all resulting buffers are no longer used. Furthermore we need to keep track of the original
//pointer returned by malloc & co so we know which one to pass to free().
typedef struct {
unsigned int i; //reference counter
void *ptr; //original pointer returned by malloc that needs to be passed to free()
} mcb_t;
//Definition of a memory buffer
typedef struct {
void *ptr; //pointer to the buffer
size_t n; //size of the buffer in bytes
mcb_t *mcb; //meta information needed for malloc/free operations
#ifdef ENABLE_MBUFFER_CHECK
int check_flag;
#endif
} mbuffer_t;
//Initialize memory buffer subsystem
int mbuffer_system_init();
//Shutdown memory buffer subsystem
int mbuffer_system_destroy();
//Initialize a memory buffer that has been manually or statically allocated
//The mbuffer system will not attempt to free argument *m
int mbuffer_create(mbuffer_t *m, size_t size);
//Make a shallow copy of a memory buffer
mbuffer_t *mbuffer_clone(mbuffer_t *m);
//Make a deep copy of a memory buffer
mbuffer_t *mbuffer_copy(mbuffer_t *m);
//Free a memory buffer
void mbuffer_free(mbuffer_t *m);
//Resize a memory buffer
//Returns 0 if the operation was successful
int mbuffer_realloc(mbuffer_t *m, size_t size);
//Split a memory buffer m1 into two buffers m1 and m2 at the designated location
//Returns 0 if the operation was successful
int mbuffer_split(mbuffer_t *m1, mbuffer_t *m2, size_t split);
#endif //_MBUFFER_H_