C memory (v0.9)

From Native Big Data Documentation
Jump to: navigation, search


C memory API

NBD memory is managed by arenas. An arena is a collection of allocated objects that can be efficiently deallocated all at once. See [[1]] for more information. Every time something is created from C language in NBD, it is stored in an arena. When the execution of something ends all the used arenas are deleted and the reserved memory is returned to the system. Memory reserved using malloc, calloc, strdup don't use arenas. We discourage using these functions in NBD native modules.


Using vars and C pointers

All the internal objects in NDB are of type 'var'. A 'var' can be a value or a pointer to a struct (objects). vars are non-typed variables and can reference numbers, strings, arrays, ... NBD provides an API to know what is the type of a var. Often this functionality is called reflection [[2]]. Generically C Pointers can be used as vars but they must be 16-bit aligned. Pointer to functions can be automatic 16-bit aligned by gcc using the parameter '-falign-functions=16'. Heap allocated object will be always 16-bit aligned using Arenas because arenas will always return 16-bit aligned memory.

Static allocated strings will be 16-bit aligned using the $T macro:

  • $T ( const char "..."): Creates a constant char * with 16-bit alignment.
char *mytext = $T("THis text will be stored in a 16-bit aligned memory block");
var txt = $POINTER(mytext);     // creates a var that represents the created C pointer.

IF you want to use pointers to automatic variables macro ALIGNED must be used.

  • $ALIGNED ( declaration ): Creates a C variable in a 16 bit aligned position of stack memory.
// creation of an aligned int 
$ALIGNED(int a) = 34;  
// now &a is 16-bit aligned 
var p = $POINTER(&a);

These macros have the following declaration:

#define $T(_x_) ({ static char __x__[] __attribute__ ((aligned (16))) = _x_;__x__; })
#define $ALIGNED(_decl_)  _decl_ __attribute__ ((aligned (16)))

Arena API

These macros will allow to use arenas.

  • $A . Returns an arena.

Variants:

  • $A(number)  : Returns a new arena with size 'number' bytes. Number must be signed or unsigned int or int64_t .
// creation of an arena with 1Kb of free memory 
var arena = $A(1024);

The arena will have 1kb of free memory. If more than 1kb is needed, the arena will grown automatically as needed. The predefined size of 1kb is used to optimize the allocated memory.


  • $A(var)  : Returns the arena used by an existing object.
var arena_1 = $A(1024);    // create an arena
var hash    = $H(arena_1); // create a hash in arena_1
// ...
var arena_2 = $A(hash);       // arena_2 points to the arena of hash (arena_1 in this example)


  • $A_malloc(arena, type, n ) : Returns space to store n type objects. (space will be n * sizeof(type)).

The space will be reset to zeros.

var arena = $A(1024);    // create an arena
char *pool = $A_malloc(arena, char , 1024); // create a buffer of 1024 bytes
var **m    = $A_malloc(arena, var * , 1024);   // create a list of 1024 var pointers.
var *k     = $A_malloc(arena, var   , 512);    // create a list of 512  vars.
double *m  = $A_malloc(arena, double , 128);   // create a list of 128 doubles.
// ...


  • $A_destroy(arena) : Frees arena and frees all the allocated memory. Registered destructors with $A_reg will be called before the memory cleaning.
var arena = $A(1024);    // create an arena
char *pool = $A_malloc(arena, char , 1024); // create a buffer of 1024 bytes
var **m = $A_malloc(arena, var * , 1024);   // create a list of 1024 var pointers.
// ...
$A_destroy(arena);
  • $A_reset(arena) : Frees objects stored in arena but don't returns the memory to the system. Registered destructors with $A_reg will be called.

Memory in the arena is reusable but is not returned to the system. Memory will not be set to zeros. The arena can be reused as a new arena.

var arena = $A(1024);
for (int i=0;i<100;i++) {
	char *buffer = $A_malloc(arena,char,100);
	snprintf(buffer,99, "number %d", i);
	var s = $S(arena, buffer);
	$TRACE(s);
	$A_reset(arena);
}


  • $A_reg(arena, var o, void (*f) (var o)) : Register a destructor for o var.

Sometimes deleting objects needs to close connections or free non arena-resources. Every time an object, that uses non-arena resources, is created its destructor must be registered to prevent leaks.

void destructor(var o) {
	conn_t *oo = $POINTER(o);
	// destrucction code
	close(oo);
}
var arena = $A(1024);    // create an arena
conn_t *connection = $A_malloc(arena, conn_t, 1);
$A_reg(arena, $P(connection), destructor);
$A_destroy(arena); // destroy an arena and free memory and resources.


  • $AB(arena, code) : Creates a block with a temporal arena.

The arena can be used inside the block and will be destroyed when the execution go out the block even if a exception is throwed from the block.

$AB( tmp_a , {
		var s = $STRING(tmp_a, $TEXT("abcde"));
		var h = $H(tmp_a);
		...
	}
);
  • $A_migrate(o, arena_from, arena_to): Moves a var from arena_from to arena_to.

Only vars in arena_from will be migrated (cloned). Other vars will remain in its original arena. The result will be a var not stored in arena_from.

	var a1 = $A(10000);
	var a2 = $A(10000);
	var b  = $A(10000);

	var s1 = $S( a1, $TEXT("Text to be migrated")  );
	var s2 = $S( a2, $TEXT("Text to not be migrated")  );

	var ar = $AR(a1, s1,s2); // creates the array [s1,s2]
	
	var ar2 = $A_migrate(ar, a1,b); // ar will be cloned in b arena and all objects inside ar and stored in a1 will be moved to b
	$A_destroy(a1): // ar2 and chilren are safe objects. a1, s1 and ar are not safe !!!
	$TRACE ($GET(ar2,0);  // will print [ "Text to be migrated" , "Text to not be migrated" ]
);