APR provides builtin functions for managing memory, and a few other
basic resources such as files, sockets, and mutexes. But there is
no requirement to use these. An alternative is to use native
allocation functions, and explicitly register a cleanup with the pool:
mytype* myvar = malloc(sizeof(mytype)) ;
apr_pool_cleanup_register(pool, myvar, free, apr_pool_cleanup_null) ;
or
FILE* f = fopen(filename, "r") ;
apr_pool_cleanup_register(pool, f, fclose, apr_pool_cleanup_null) ;
will delegate responsibility for cleanup to the pool, so that no further
action from the programmer is required. But bear in mind that native
functions may be less portable than APR equivalents.
This method generalises to resources opaque to Apache and APR.
For example, to open a database connection and ensure it is
closed after use:
MYSQL* sql = NULL ;
sql = mysql_init(sql) ;
if ( sql == NULL ) { log error and return failure ; }
apr_pool_cleanup_register(pool, sql, mysql_close,
apr_pool_cleanup_null) ;
sql = mysql_real_connect(sql, host, user, pass, dbname, port, sock, 0) ;
if ( sql == NULL ) { log error and return failure ; }
Note that APR provides an altogether better method for managing database
connections - this will be the subject of another article.
As a second example, consider XML processing:
xmlDocPtr doc = xmlReadFile(filename)
apr_pool_cleanup_register(pool, doc, xmlFreeDoc,
apr_pool_cleanup_null) ;
/* now do things with doc, that may allocate further memory
managed by the XML library but will be cleaned by xmlFreeDoc
*/
Integrating C++ destructor-cleanup code provides yet another example:
Suppose we have:
class myclass {
public:
virtual ~myclass() { do cleanup ; }
// ....
} ;
We define a C wrapper:
void myclassCleanup(void* ptr) { delete (myclass*)ptr ; }
and register it with the pool when we allocate myclass:
myclass* myobj = new myclass(...) ;
apr_pool_cleanup_register(pool, (void*)myobj, myclassCleanup,
apr_pool_cleanup_null) ;
// now we've hooked our existing resource management from C++
// into apache and never need to delete myobj