lunedì 27 agosto 2007

Pool di risorse e gestione della memoria

Recentemente mi sono messo a meditare sulla gestione della memoria in Java: visto l’alto costo della new, pensavo di creare un generico contenitore template Pool in grado di contenere e riutilizzare risorse senza invocare la new; chiaramente gli oggetti avrebbero dovuto essere “abilitati” al riutilizzo attraverso un metodo di “rigenerazione” che facesse lo stesso lavoro di un’invocazione al distruttore + un’invocazione al costruttore senza coinvolgere il gestore della memoria della virtual machine (in C++ basterebbe sovraccaricare l’operatore di assegnamento). A questo punto avrei voluto implementare un qualche sistema per “sentire” l’uscita dallo scope di una reference all’oggetto per poter indicare al Pool quando segnare l’oggetto come inutilizzato e renderlo disponibile per essere riutilizzato. Non ci sono riuscito, e mi sono accontentato di un metodo “release” da invocare manualmente, rendendo così l’utilizzo di questo sistema soggetto ai soliti errori di memory leak, e quindi inutile.

Così ho cominciato a ragionare in C++: il meccanismo più efficiente per abbattere i costi dell’allocazione di memoria (in particolare la copia di oggetti complessi) è l’utilizzo di referenze come parametri di funzioni che consentono un comportamento “Java like” (e quindi il polimorfismo…) in modo totalmente trasparente al programmatore (che non deve gestire cioè manualmente la memoria): il limite delle referenze è che funzionano solo in una direzione (verso l’alto dello stack) e quindi non possono essere utilizzate per delle object factory. La soluzione è utilizzare gli auto_ptr, per consentire l’utilizzo di simil-referenze anche verso il basso dello stack: è così possibile creare una funzione del tipo:auto_ptr<resourcehandler> getResource(…);

A questo punto il distruttore di ResourceHandler avrà il compito di “rilasciare” la risorsa dal pool, e questo rilascio avverrà in automatico all’atto dell’uscita dallo scope dell’auto_ptr (bisogna quindi definire come virtuale il distruttore, per poter specializzare liberamente ResourceHandler).

Rimane però un problema: gli auto_ptr non possono essere utilizzati nei contenitori stl standard (o forse si… non mi ricordo come funzionano gli allocatori…). Certo che se Java mettesse a disposizione una callback tipo “finalize” (chiamiamola “referenceOutOfScope”) all’uscita dello scope di una referenza, il suo potenziale espressivo crescerebbe molto, mantenendo comunque la semplicità della gestione automatica della memoria.

Nessun commento: