Newsgroup: it.comp.lang.c++
Titolo: allocazioni di memoria

Ciao,
ho un problema nel comprendere bene questo codice.
MemoryManager::MemoryManager()
{
	// build a 32-byte aligned array of BVHNodes
	uint numNodes = 200000;
	nodeArray = (char*)(new BVHNode[numNodes]);
	unsigned long addr = (unsigned long)nodeArray;
	//this means that we get correct address with 5 LSB 0
	//this important as we discard the 3 LSB in tree node for split axis
and node type,
	//besides we add nodes of chuncks of 2 nodes = 16 bytes so all
adresses are based correctly
	nodePtr = (BVHNode*)((addr + 32) & (0xffffffff - 31));
}
In particolare, questo è il costruttore della classe seguente:
class MemoryManager
{
public:
	MemoryManager();
	//returns 2 nodes = 16 byes and advances the nodeptr 2 node
	BVHNode* NewBVHNodePair();
private:
	PrimitiveList* primitiveList;//pool for primitive list
	char *nodeArray;
	BVHNode* nodePtr;
};
Non capisco cosa avviene nel costruttore... cioè io credo che venga
allocato un array di oggetti di tipo BVHNode (ho inserito il codice
relativo in calce) e poi con il casting a (char*) assegno l'indirizzo
dell'array, ma se non sbaglio, un puntatore di questo tipo ha
dimensioni di 1 byte, quindi l'indirizzo sarà collocato in questo
spazio, si tratta quindi della prima locazione di questo array?
Poi cosa accade quando viene fatto il casting ad unsigned long di
questo puntatore? L'indirizzo che prima era inserito in un 1 byte ora
verrà messo in 4 byte senza segno?
Poi in questa linea :
nodePtr = (BVHNode*)((addr + 32) & (0xffffffff - 31));
non capisco quel + 32, insomma, avrei bisogno di una mano per capire
bene cosa accade con tutte questi passaggi.
--
classe BVHNode:
class BVHNode
{
public:
	BVHNode() : data( 6 ) {}; //data = 6 = b110 = leaf,z-axis
	void SetAxis( int axis ) { data = (data & 0xfffffffc) + axis; } //
olddata & [11....1100] + axis
	int GetAxis() { return data & 3; } //data & [00.....11] to get the
least significant bits
	void SetSplitPos( float pos ) { splitvalue = pos; }
	float GetSplitPos() { return splitvalue; }
	void SetLeft( BVHNode* left ) { data = (unsigned long)left + (data &
7); } //[data & 111] to keep split and node type unchanged
	BVHNode* GetLeft() { return (BVHNode*)(data&0xfffffff8); }// [data &
11.....1000] to return only data
	BVHNode* GetRight() { return ((BVHNode*)(data&0xfffffff8)) + 1; }//
right = left+1
	bool IsLeaf() { return ((data & 4) > 0); }//4 = b100 leaf
	void SetLeaf( bool isleaf ) { data = (isleaf)?(data|4):
(data&0xfffffffb); }//B = b1011
private:
	//8 bytes is enough for every thing
	float splitvalue;
	//data: 32 bits b31b30......b1b0
	//b1b0 : axis 0 = X-axis, 1 = Y-axis, 2 = Z-axis
	//b2 leaf/interal [0 internal, 1 leaf]
	//b31...b3 : 29 bits , if interal position of left node, right node
follow it
	//if leaf give a pointer to first primitive in objects list in this
node
	unsigned long data;
public://todo boxing these variables
	uint start;//start index of the refernced triangles in the triangles
array
	uint length;//number of triangles in the refenced triangles array
	AABB box;
};

 bene cosa accade con tutte questi passaggi. --
Allora, il cast a char* semplicemente prende l'indirizzo dell'array di 
oggetti BVHNode, e lo memorizza in una variabile grossa 4 byte (dipende 
dal compilatore e dall'architettura), in quanto si tratta di un indirizzo 
in memoria.
Il successivo cast a unsigned long non cambia nulla, semplicemente addr 
avrà al suo interno un valore X che rappresenta la locazione di memoria 
dell'array di oggetti BVHNode, ma è trattato come numero.
La riga successiva, ovvero:
nodePtr = (BVHNode*)((addr + 32) & (0xffffffff - 31));
Prende l'indirizzo dell'array, somma 32 e fa un AND bit a bit tra lui e 
tutti uni (0xffffffff) TRANNE gli ultimi 5 bit (31 decimale è uguale agli 
ultimi 5 bit a 1 in binario).
Il risultato dell'operazione è un valore multiplo di 32 a cui ho aggiunto 
32 (se togliessi solo i 5 bit meno significativi andrei poi a puntare ad 
un indirizzo che non ho allocato io).
Castato a oggetto BVHNode per poter correttamente manipolare l'array di 
oggetti con l'aritmetica dei puntatori successivamente.
Vorrei farti notare che se la new potrebbe restituire una locazione di 
memoria non multipla di 32, mentre tu inizierai a gestire gli oggetti a 
partire da locazioni multiple di 32, per cui perderai i primi X byte con 
X < 16 se addr % 32 != 0 (se è quindi multiplo).
Altro problema è il fondo dell'array, perchè avendo allocato:
200000*sizeof(BVHNode) spazio, e avendo tu tolto X byte iniziali, se 
riempi l'array con effettivamente 200000 BVHNode andrai a sforare.
Se ho fatto errori, me ne scuso e accetto correzioni :-)

 X < 16 se addr % 32 != 0 (se è quindi multiplo).
Mi auto correggo l'italiano (scritto in fretta)
Vorrei farti notare che la new potrebbe restituire una locazione di




E anche un piccolo errorino
Vorrei farti notare che la new potrebbe restituire una locazione di 
memoria non multipla di 32, mentre tu inizierai a gestire gli oggetti a
partire da locazioni multiple di 32, per cui perderai i primi X byte con
X < 32 se addr % 32 != 0 (se è quindi multiplo).