Could we move Arena.h to tscpp/util, and just add:

Arena & tsapi::txnArena(TSHttpTxn txn);

For your finalizer example, when would that be better than using
Cleanup.h?  That is, when would it be better than having the vector be a
data member of the TxnAuxData class you provide as a parameter to the
TxnAuxDataMgr template?

On Wed, Dec 6, 2023 at 8:00 PM Alan Carroll <a...@network-geographics.com>
wrote:

> Proposed Transaction based memory allocation API
>
> TSTxnAlloc
> **********
>
> Traffic Server Transaction based memory allocation.
>
> Synopsis
> ========
>
> .. code-block:: cpp
>
>     #include <ts/ts.h>
>
> .. function:: swoc::MemSpan<void> TSTxnAlloc(TSHttpTxn txn, size_t bytes)
> .. function:: swoc::MemSpan<void> TSTxnAllocAligned(TSHttpTxn txn, size_t
> bytes, size_t align)
> .. function:: template < typename T > T * TSTxnAllocInstance();
> .. function:: template < typename T > swoc::MemSpan<T>
> TSTxnAllocArray(size_t count);
> .. function:: swoc::TextView TSTxnLocalizeString(TSHttpTxn txn,
> swoc::TextView s)
> .. function:: swoc::TextView TSTxnLocalizeCString(TSHttpTxn txn, char
> const * s)
> .. function:: template < typename F > void TSTxnFinalize(TSHttpTxn txn, F
> && f)
>
> Description
> ===========
>
> These functions are used to allocate memory that has the same lifetime as
> a transaction. This has two differences from
> normal allocation which are frequently advantageous for plugins.
>
> *  Allocation is much faster than :code:`malloc` or equivalent.
> *  The memory is released at the end of the transaction automatically.
>
> The only function in this group that does not allocate is
> :func:`TSTxnFinalize`. Instead this provides a functor
> which is invoked just before the transaction local memory is released.
>
> :func:`TSTxnAlloc` allocates a block of memory of size :arg:`bytes`.
>
> :func:`TSTxnAllocAligned` allocates a block of memory of size :arg:`bytes`
> that is aligned at a multiple of :arg:`align`,
> which must be a power of 2.
>
> :func:`TSTxnAllocInstance` allocates an instance of a type :code:`T` with
> the required alignment for :arg:`T`,
> calls the default constructor for :code:`T`, and the returns the pointer.
>
> :func:`TSTxnAllocArray` allocates a block of memory of size and alignment
> to hold :arg:`count` instances of :code:`T`. These
> are not initialized / constructed.
>
> :func:`TSTxnLocalizeString` copies the string :arg:`s` to transaction
> local memory and returns a view of the copied string.
>
> :func:`TSTxnLocalizeCString` copies a C string (nul character terminated)
> :arg:`s` to transaction local memory and returns a view of the copied
> string.
>
> :func:`TSTxnFinalize` creates a finalizer for the transaction which are
> described in :ref:`finalizers`.
>
> Notes
> =====
>
> In general this memory should avoid referencing memory outside of
> transaction local memory. Strings are the archetype
> as a string is complete in itself and requires no cleanup beyond
> deallocation. For variable sized structures it is
> possible to use :code:`swoc::IntrusiveDList` to create lists which reside
> entirely in transaction local memory and
> therefore require no addtional cleanup.
>
> .. _finalizers::
>
> Finalizers
> ----------
>
> If cleanup is unavoidable then a :em:`finalizer` can be used. This is a
> functor that is invoked just before cleaning
> up transaction local memory which is intended to perform addtional
> cleanup. This imposes several restrictions
>
> *  The finalizer itself must not require any cleanup beyond deallocation.
> One aspect is the functor instance must
>    not contain any non-transaction local allocated memory.
> *  The finalizer must only do allocation related cleanup. It must not call
> any TS plugion API calls. The transaction
>    object is likely to be in an unusable state when the finalizer is
> invoked.
>
> For an example finalizer, suppose the allocation is used to hold a
> :code:`std::vector<size_t>`. Simply releasing the
> memory will leak the vector elements, so the vector must be destructed.
> This can be handled by a finalizer that looks
> like
>
> .. code-block:: cpp
>
>    auto * vecp = TSTxnAllocInstance<std::vector<size_t>>(txn);
>    TSTxnFinalizer(txn, [=]() -> void { delete vecp; });
>
> The pointer to the allocated vector is captured by the lambda and when the
> transaction local memory is released the
> vector contents are also released. Be very very careful or (better) avoid
> entirely capture by reference, as the target of the
> reference is likely to be long out of scope when the finalizer is invoked.
>
> See also
> ========
>
> :manpage:`TSAPI(3ts)`
> +
>

Reply via email to