Skip to content

Using APR Pools

Nick Satterly edited this page Jul 31, 2013 · 2 revisions

From Subversion, we have learned a lot about how to use pools in a heavily structured/object-based environment. Apache httpd is a completely different beast: "allocate a request pool. use it. destroy it."

In a complex app, that request-style of behavior is not present. Luckily, the "proper" use of pools can be described in just a few rules:

  • Objects should not have their own pools. An object is allocated into a pool defined by the constructor's caller. The caller knows the lifetime of the object and will manage it via the pool. Generally, this also means that objects will not have a "close" or a "free" since those operations will happen implicitly as part of the destruction of the pool the objects live within.
  • Functions should not create/destroy pools for their operation; they should use a pool provided by the caller. Again, the caller knows more about how the function will be used, how often, how many times, etc. Thus, it should be in charge of the function's memory usage.

As an example, the caller might know that the app will exit upon the function's return. Thus, the function would be creating extra work if it built and destroyed a pool. Instead, it should use the passed-in pool, which the caller is going to be tossing as part of app-exit anyways.

  • Whenever an unbounded iteration occurs, a subpool should be used. The general pattern is:
    subpool = apr_create_subpool(pool);
    for (i = 0; i < n; ++i) {
      apr_pool_clear(subpool);

      do_operation(..., subpool);
    }
    apr_pool_destroy(subpool);

This pattern prevents the 'pool' from growing unbounded and consuming all of memory. Note that it is slightly more optimal to clear the pool on loop-entry. This pattern also allows for a 'continue' to occur within the loop, yet still ensure the pool will be cleared.

  • Given all of the above, it is pretty well mandatory to pass a pool to every function. Since objects are not recording pools for themselves, and the caller is always supposed to be managing memory, then each function needs a pool, rather than relying on some hidden magic pool. In limited cases, objects may record the pool used for their construction so that they can construct sub-parts, but these cases should be examined carefully. Internal pools can lead to unbounded pool usage if the object is not careful.

[1] Using APR Pools, Greg Stein, http://svn.apache.org/viewcvs.cgi/*checkout*/apr/apr/trunk/docs/pool-design.html