Asterisk - The Open Source Telephony Project  18.5.0
Object Model implementing objects and containers.

This module implements an abstraction for objects (with locks and reference counts), and containers for these user-defined objects, also supporting locking, reference counting and callbacks.

The internal implementation of objects and containers is opaque to the user, so we can use different data structures as needs arise.

USAGE - OBJECTS

An ao2 object is a block of memory that the user code can access, and for which the system keeps track (with a bit of help from the programmer) of the number of references around. When an object has no more references (refcount == 0), it is destroyed, by first invoking whatever 'destructor' function the programmer specifies (it can be NULL if none is necessary), and then freeing the memory. This way objects can be shared without worrying who is in charge of freeing them. As an additional feature, ao2 objects are associated to individual locks.

Creating an object requires the size of the object and a pointer to the destructor function:

struct foo *o;

o = ao2_alloc(sizeof(struct foo), my_destructor_fn);

The value returned points to the user-visible portion of the objects (user-data), but is also used as an identifier for all object-related operations such as refcount and lock manipulations.

On return from ao2_alloc():

ao2_ref(o, +1) can be used to modify the refcount on the object in case we want to pass it around.

USAGE - CONTAINERS

An ao2 container is an abstract data structure where we can store ao2 objects, search them (hopefully in an efficient way), and iterate or apply a callback function to them. A container is just an ao2 object itself.

A container must first be allocated, specifying the initial parameters. At the moment, this is done as follows:

<b>Sample Usage:</b>
struct ao2_container *c;
my_hash_fn, NULL, my_cmp_fn);

where

A container knows little or nothing about the objects it stores, other than the fact that they have been created by ao2_alloc(). All knowledge of the (user-defined) internals of the objects is left to the (user-supplied) functions passed as arguments to ao2_container_alloc_hash().

If we want to insert an object in a container, we should initialize its fields – especially, those used by my_hash_fn() – to compute the bucket to use. Once done, we can link an object to a container with

ao2_link(c, o);

The function returns NULL in case of errors (and the object is not inserted in the container). Other values mean success (we are not supposed to use the value as a pointer to anything). Linking an object to a container increases its refcount by 1 automatically.

Note
While an object o is in a container, we expect that my_hash_fn(o) will always return the same value. The function does not lock the object to be computed, so modifications of those fields that affect the computation of the hash should be done by extracting the object from the container, and re-inserting it after the change (this is not terribly expensive).
A container with a single buckets is effectively a linked list. However there is no ordering among elements.