Collaboration diagram for Pool Debugging functions:


void apr_pool_owner_set (apr_pool_t *pool, apr_uint32_t flags)
void apr_pool_join (apr_pool_t *p, apr_pool_t *sub) __attribute__((nonnull(2)))
apr_pool_tapr_pool_find (const void *mem)
apr_size_t apr_pool_num_bytes (apr_pool_t *p, int recurse) __attribute__((nonnull(1)))
void apr_pool_lock (apr_pool_t *pool, int flag)

Detailed Description

pools have nested lifetimes – sub_pools are destroyed when the parent pool is cleared. We allow certain liberties with operations on things such as tables (and on other structures in a more general sense) where we allow the caller to insert values into a table which were not allocated from the table's pool. The table's data will remain valid as long as all the pools from which its values are allocated remain valid.

For example, if B is a sub pool of A, and you build a table T in pool B, then it's safe to insert data allocated in A or B into T (because B lives at most as long as A does, and T is destroyed when B is cleared/destroyed). On the other hand, if S is a table in pool A, it is safe to insert data allocated in A into S, but it is not safe to insert data allocated from B into S... because B can be cleared/destroyed before A is (which would leave dangling pointers in T's data structures).

In general we say that it is safe to insert data into a table T if the data is allocated in any ancestor of T's pool. This is the basis on which the APR_POOL_DEBUG code works – it tests these ancestor relationships for all data inserted into tables. APR_POOL_DEBUG also provides tools (apr_pool_find, and apr_pool_is_ancestor) for other folks to implement similar restrictions for their own data structures.

However, sometimes this ancestor requirement is inconvenient – sometimes it's necessary to create a sub pool where the sub pool is guaranteed to have the same lifetime as the parent pool. This is a guarantee implemented by the caller, not by the pool code. That is, the caller guarantees they won't destroy the sub pool individually prior to destroying the parent pool.

In this case the caller must call apr_pool_join() to indicate this guarantee to the APR_POOL_DEBUG code.

These functions have an empty implementation if APR is compiled with #APR_POOL_DEBUG not set.

Function Documentation

◆ apr_pool_find()

apr_pool_t* apr_pool_find ( const void *  mem)

Find a pool from something allocated in it.

memThe thing allocated in the pool
The pool it is allocated in

◆ apr_pool_join()

void apr_pool_join ( apr_pool_t p,
apr_pool_t sub 

Guarantee that a subpool has the same lifetime as the parent.

pThe parent pool
subThe subpool

◆ apr_pool_lock()

void apr_pool_lock ( apr_pool_t pool,
int  flag 

Lock a pool

poolThe pool to lock
flagThe flag

◆ apr_pool_num_bytes()

apr_size_t apr_pool_num_bytes ( apr_pool_t p,
int  recurse 

Report the number of bytes currently in the pool

pThe pool to inspect
recurseRecurse/include the subpools' sizes
The number of bytes

◆ apr_pool_owner_set()

void apr_pool_owner_set ( apr_pool_t pool,
apr_uint32_t  flags 

Guarantee that a pool is only used by the current thread. This should be used when a pool is created by a different thread than the thread it is using, or if there is some locking in use to ensure that only one thread uses the pool at the same time.

poolThe pool
flagsFlags, currently unused