#ifndef APR_HXX #define APR_HXX #include #include #include // Build a cleanup function for type T, this is intended as a shortcut // to build the cleanup function needed by apr::pool::allocate. #define APR_DECLARE_CLEANUP(T) \ static apr_status_t \ cleanup(T *p) \ { \ p->~T(); \ \ return APR_SUCCESS; \ } namespace apr { extern "C" { typedef apr_status_t (*pool_cleanup_func) (void *); } void initialize() { apr_initialize (); atexit (apr_terminate); } class pool { public: pool() { apr_pool_create (&m_pool, NULL);; } pool(pool & parent) { apr_pool_create (&m_pool, parent.m_pool);; } void clear() { apr_pool_clear (m_pool); } class cleaner { public: cleaner(pool & p) : m_pool(p) {} ~cleaner() { m_pool.clear(); } private: pool & m_pool; }; ~pool() { apr_pool_destroy (m_pool);; } template T *allocate() { void *v = apr_palloc (m_pool, sizeof (T)); T *t = new (v) T(); apr_pool_cleanup_register ( m_pool, t, reinterpret_cast(T::cleanup), NULL ); return t; } // XXX I'm not sure i like the interface here. The template parameter // is basically just there so you don't need to cast the return val, // but we don't even use it's size info, which could be useful, and // it still results in extra typing. On the other hand, using the // size of T means that alloc and calloc's arguments are different // than the underlying apr_palloc/apr_pcalloc, which is a bad thing. template T * alloc(apr_size_t len) { return reinterpret_cast(apr_palloc (m_pool, len)); } template T * calloc(apr_size_t len) { return reinterpret_cast(apr_pcalloc (m_pool, len)); } private: apr_pool_t *m_pool; }; } #endif // APR_HXX