\newpage
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Memory arenas} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\label{sec:arenas}

Many user applications require a different memory allocator than the basic C
\verb'malloc' and \verb'free', and some applications require multiple allocators
to be used at the same time.

GraphBLAS 10.4.0 introduces a new feature to the library to support the use of
multiple allocators: {\em memory arenas}.  An arena is simply a set memory
allocator routines with the same API as the C \verb'malloc' and \verb'free', plus
optional \verb'realloc' and \verb'calloc' methods.

Each object in GraphBLAS lives in one or two memory arenas, depending on the
object.  The \verb'GrB_Matrix', \verb'GrB_Vector', and \verb'GrB_Scalar' can
use two arenas: a {\em header arena} and a {\em data arena}.  Each object in
GraphBLAS is a pointer to a struct with opaque content, typically at most a few
hundred bytes in size, regardless of the size of the object.  The
\verb'GrB_Matrix A' is simply a pointer to this struct, which is the header of
the object \verb'A'.  Changing the header of a matrix, vector, or scalar will
change the pointer to the object itself (the \verb'GxB_Matrix_set_arenas'
method does this, for example).

The entries in a matrix, vector, or scalar are held in a set of integer arrays
for row/column indices and offsets, plus a numerical array for the data type.
These arrays are all in the data arena of the matrix, vector, or scalar.

All other objects have only a single arena, the header arena.  The serialized
blob is not a GraphBLAS object; it is created in the default data arena.

By default, only a single memory arena is used for all objects, and this arena
defaults to the standard C
\verb'malloc'/\verb'calloc'/\verb'realloc'/\verb'free' methods.  All arena
features described in this section are backward compatible with prior versions
of GraphBLAS, so if no additional arenas are needed, nothing needs to change in
applications that used GraphBLAS versions prior to 10.4.0 (including the
MATLAB/Octave interface).

Objects in different arenas can be mixed arbitrarily, so for any given
GraphBLAS method, not all of its parameters need to refer to objects that are
all in the same arena.

%-------------------------------------------------------------------------------
\subsection{Creating arenas}
%-------------------------------------------------------------------------------

The default arena is initialized when \verb'GrB_init' or \verb'GxB_init' is
called.  \verb'GxB_init' takes in the four pointers to the \verb'malloc',
\verb'calloc', \verb'realloc', and \verb'free' functions.  This becomes arena
0, the default arena (\verb'GrB_DEFAULT', which is defined as zero).

Once an arena is initialized, it cannot be deleted except by a call to
\verb'GrB_finalize', which resets all arenas (including the default arena).
The macro \verb'GxB_NARENAS' is set in \verb'GraphBLAS.h' and defines the
maximum number of arenas (8 in GraphBLAS version 10.4.0).

New arenas can be initialized after \verb'GrB_init' with the
\verb'GxB_arena_init' method.

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GxB_arena_init     // create a new arena
(
    // input
    int arena,              // 1 to GxB_NARENAS-1
    void * (* user_malloc_function  ) (size_t),         // required
    void * (* user_calloc_function  ) (size_t, size_t), // not used
    void * (* user_realloc_function ) (void *, size_t), // optional, can be NULL
    void   (* user_free_function    ) (void *)          // required
) ;
\end{verbatim}
}\end{mdframed}

Arena 0 is only initialized by
\verb'GrB_init' or \verb'GxB_init', so the \verb'arena' parameter in
\verb'GxB_arena_init' can be in the range 1 to \verb'GxB_NARENAS-1'.

Just as in \verb'GxB_init', the \verb'calloc' and \verb'realloc' methods are
optional.  GraphBLAS currently makes no use of the \verb'calloc' method itself,
but it can be returned by \verb'GrB_get'.  It uses the \verb'realloc' method if
avaliable; otherwise if this function is NULL, it uses \verb'malloc' and
\verb'memcpy' in its place.

To retrieve these function pointers after the arena is initialized, use the following:

    {\footnotesize
    \begin{verbatim}
    GrB_Global_get_VOID (GrB_GLOBAL, &malloc_func,  GxB_ARENA_MALLOC  + arena) ;
    GrB_Global_get_VOID (GrB_GLOBAL, &calloc_func,  GxB_ARENA_CALLOC  + arena) ;
    GrB_Global_get_VOID (GrB_GLOBAL, &realloc_func, GxB_ARENA_REALLOC + arena) ;
    GrB_Global_get_VOID (GrB_GLOBAL, &free_func,    GxB_ARENA_FREE    + arena) ; \end{verbatim}}

The \verb'GxB_arena_initialized' method can be used to determine if an
arena has been initialized or not.

\begin{mdframed}[userdefinedwidth=6in]
{\footnotesize
\begin{verbatim}
GrB_Info GxB_arena_initialized  // determine if arena has been initialized
(
    // output
    int *flag,              // returns true if the arena has been initialized
    // input
    int arena               // 0 to GxB_NARENAS-1
) ;
\end{verbatim}
}\end{mdframed}

%-------------------------------------------------------------------------------
\subsection{Using arenas via the global or per-thread context}
%-------------------------------------------------------------------------------
\label{arena_global}

Once an arena is initialized, it can be used to create new GraphBLAS objects
using one of two methods:  (1) per-object with methods such as
\verb'GxB_Matrix_new_arena' (see the the next section) or (2) for all objects
using the global context or a specific \verb'Context' object for any given
thread in the user application (described below). 

For method (2), the get/set options are used.  To set the global default
arenas, use:

    {\footnotesize
    \begin{verbatim}
    GrB_set (GrB_GLOBAL, arena, GxB_ARENA_DATA) ;
    GrB_set (GrB_GLOBAL, arena, GxB_ARENA_HEADER) ; \end{verbatim}}

To set the arenas via a \verb'Context' object, use:

    {\footnotesize
    \begin{verbatim}
    GxB_set (Context, arena, GxB_ARENA_DATA) ;
    GxB_set (Context, arena, GxB_ARENA_HEADER) ; \end{verbatim}}

For the \verb'Context' object, the \verb'Context' must also be engaged for
these settings to be used.  See Sections~\ref{context}, \ref{get_set_context},
and \ref{get_set_global} for details.

Once either of the above settings are used, all subsequent newly-created
objects will be in the new arenas.  For example,
\verb'GrB_Matrix_new (&A, ...)' creates \verb'A' in the header and
data arenas determined by these two arena settings.

These settings can be queried via \verb'GrB_get':

    {\footnotesize
    \begin{verbatim}
    int32_t arena ;
    GrB_get (GrB_GLOBAL, &arena, GxB_ARENA_DATA) ;
    GrB_get (GrB_GLOBAL, &arena, GxB_ARENA_HEADER) ;
    GxB_get (Context, &arena, GxB_ARENA_DATA) ;
    GxB_get (Context, &arena, GxB_ARENA_HEADER) ; \end{verbatim}}

This is the simplest method to use different arenas, but it does not allow
control on a per-object basis.  That control is presented in the next section.

%-------------------------------------------------------------------------------
\subsection{Using arenas via per-object methods}
%-------------------------------------------------------------------------------

GraphBLAS 10.4.0 introduces a suite of constructor methods that take in
specific header and data arena parameters.  Instead of using the default header
and data arenas defined by methods discussed in Section~\ref{arena_global},
they use these parameters to create their output objects in the given arenas.
Objects with a single arena (the header or data) include one extra parameter,
while objects with two arenas (matrices, vectors, and scalars) take two extra
parameters.  The leading input/output parameters are the same.  For methods
that have a descriptor, the descriptor remains as the last parameter.

In the table below, \verb'h' is an integer in range 0 to \verb'GxB_NARENAS-1'
that defines the header arena for the new object.  The methods in the right
column have identical parameters as the methods in the left column,
with the addition of the single \verb'h' parameter.

\vspace{0.1in}
\noindent
\hspace{-0.5in}
{\footnotesize
\begin{tabular}{|ll|}
\hline
original method & arena-specific method and parameters \\
(default arena) & (header arena \verb'h') \\
\hline
\verb'GrB_Descriptor'           & \verb'GxB_Descriptor_new_arena (&d, h)' \\
\verb'GxB_Type_new'             & \verb'GxB_Type_new_arena (&type, siz, name, defn, h)' \\
\verb'GrB_UnaryOp_new'          & \verb'GxB_UnaryOp_new_arena (&op, f, z, x, name, defn, h)' \\
\verb'GrB_BinaryOp_new'         & \verb'GxB_BinaryOp_new_arena (&op, f, z, x, y, name, defn, h)' \\
\verb'GxB_BinaryOp_new_IndexOp_arena' & \verb'GxB_BinaryOp_new_IndexOp_arena (&op, idxop, theta, h)' \\
\verb'GxB_IndexBinaryOp_new'    & \verb'GxB_IndexBinaryOp_new_arena (&op, f, z, x, y, t, name, defn, h)' \\
\verb'GrB_IndexUnaryOp_new'     & \verb'GxB_IndexUnaryOp_new_arena (&op, f, z, x, y, name, defn, h)' \\
\verb'GrB_Monoid_new'           & \verb'GxB_Monoid_new_arena (&mon, op, id, h)' \\
\verb'GxB_Monoid_terminal_new'  & \verb'GxB_Monoid_terminal_new_arena (&mon, op, id, term, h)' \\
\verb'GrB_Semiring_new'         & \verb'GxB_Semiring_new_arena (&semi, add, mult, h)' \\
\verb'GxB_Context_new'          & \verb'GxB_Context_new_arena (&context, h)' \\
\verb'GxB_Iterator_new'         & \verb'GxB_Iterator_new_arena (&iter, h)' \\
\hline
\end{tabular}}
\vspace{0.05in}

The following table lists constructor methods in the left column that create
their output objects in the default header and data arenas.  In the right
column are the new methods with \verb'h' and \verb'd' input parameters that
specify the two arenas to use (both being integers in the range 0 to
\verb'GxB_NARENAS'-1).

\vspace{0.1in}
\noindent
{\footnotesize
\begin{tabular}{|ll|}
\hline
original method & arena-specific method and parameters  \\
(default arenas) & (header arena \verb'h' and data arena \verb'd') \\
\hline
\verb'GxB_Container_new'        & \verb'GxB_Container_new_arena (&container, h, d)' \\
\verb'GrB_Scalar_new'           & \verb'GxB_Scalar_new_arena (&s, t, h, d)' \\
\verb'GrB_Vector_new'           & \verb'GxB_Vector_new_arena (&v, t, n, h, d)' \\
\verb'GrB_Matrix_new'           & \verb'GxB_Matrix_new_arena (&A, t, nrows, ncols, h, d)' \\
\hline
\verb'GrB_Scalar_dup'           & \verb'GxB_Scalar_dup_arena (&s, t, h, d)' \\
\verb'GrB_Vector_dup'           & \verb'GxB_Vector_dup_arena (&w, u, h, d)' \\
\verb'GrB_Matrix_dup'           & \verb'GxB_Matrix_dup_arena (&C, A, h, d)' \\
\verb'GxB_Matrix_split'         & \verb'GxB_Matrix_split_arena (&T, m, n, trows, tcols, A, h, d, desc)' \\
\verb'GrB_Matrix_diag'          & \verb'GxB_Matrix_diag_arena (&C, v, k, h, d)' \\
\verb'GxB_Matrix_reshapeDup'    & \verb'GxB_Matrix_reshapeDup_arena (&C, A, by, nrows, ncols, h, d, desc)' \\
\verb'GxB_Matrix_deserialize'   & \verb'GxB_Matrix_deserialize_arena (&C, t, blob, siz, h, d, desc)' \\
\verb'GxB_Vector_deserialize'   & \verb'GxB_Vector_deserialize_arena (&w, t, blob, siz, h, d, desc)' \\
\hline
\end{tabular}}
\vspace{0.05in}

Finally, two new methods are introduced with a single data arena parameter,
\verb'd', listed in the following table.  These methods create the new
\verb'blob' in the data arena \verb'd'.

\vspace{0.1in}
\noindent
{\footnotesize
\begin{tabular}{|ll|}
\hline
original method & arena-specific method and parameters  \\
(default arena) & (data arena \verb'd') \\
\hline
\verb'GxB_Matrix_serialize'     & \verb'GxB_Matrix_serialize_arena (&blob, &siz, A, d, desc)' \\
\verb'GxB_Vector_serialize'     & \verb'GxB_Vector_serialize_arena (&blob, &siz, A, d, desc)' \\
\hline
\end{tabular}}
\vspace{0.05in}

%-------------------------------------------------------------------------------
\subsection{Changing the arenas of matrices, vectors, and scalars}
%-------------------------------------------------------------------------------

The header and data arenas of a \verb'GrB_Matrix A', \verb'GrB_Vector V', and
\verb'GrB_Scalar S' can change after they are created, with the following
methods.  To change just the data arenas:

{\footnotesize
\begin{verbatim}
    GrB_Matrix_set_INT32 (A, arena, GxB_ARENA_DATA) ;
    GrB_Vector_set_INT32 (V, arena, GxB_ARENA_DATA) ;
    GrB_Scalar_set_INT32 (S, arena, GxB_ARENA_DATA) ;
\end{verbatim}}

\noindent
or more simply, using the polymorphic \verb'GrB_get' and \verb'Grb_set'
methods:

{\footnotesize
\begin{verbatim}
    GrB_set (A, arena, GxB_ARENA_DATA) ;
    GrB_set (V, arena, GxB_ARENA_DATA) ;
    GrB_set (S, arena, GxB_ARENA_DATA) ;
\end{verbatim}}

The \verb'GrB_set' method cannot change the header arena, since that must
change the pointers to the opaque structs.  This changes the pointers \verb'A',
\verb'V', and \verb'S', respectively, so their handles must be passed into the
following methods:

{\footnotesize
\begin{verbatim}
    GxB_Matrix_set_arenas (&A, header_arena, data_arena) ;
    GxB_Vector_set_arenas (&V, header_arena, data_arena) ;
    GxB_Scalar_set_arenas (&S, header_arena, data_arena) ;
\end{verbatim}}

%-------------------------------------------------------------------------------
\subsection{Querying the arenas of any object}
%-------------------------------------------------------------------------------

The header and data arenas of any object can be queried with \verb'GrB_get';
using the non-polymorphic methods:

{\footnotesize
\begin{verbatim}
    GrB_Matrix_get_INT32 (A, &arena, GxB_ARENA_DATA) ;
    GrB_Vector_get_INT32 (V, &arena, GxB_ARENA_DATA) ;
    GrB_Scalar_get_INT32 (S, &arena, GxB_ARENA_DATA) ;
    GrB_Matrix_get_INT32 (A, &arena, GxB_ARENA_HEADER) ;
    GrB_Vector_get_INT32 (V, &arena, GxB_ARENA_HEADER) ;
    GrB_Scalar_get_INT32 (S, &arena, GxB_ARENA_HEADER) ;
\end{verbatim}}

Or simply use \verb'GrB_get'.  For all other objects (descriptors, operators,
types, monoids, semirings, contexts, only the header arena can be queried:

{\footnotesize
\begin{verbatim}
    GrB_get (object, &arena, GxB_ARENA_HEADER) ;
\end{verbatim}}

