Containers are data structures meant to store several objects, and perform various operations on them. Internally, objects are stored in lists, hash tables
or other data structures depending on the needs.
- NOTA BENE: at the moment the only container we support is the hash table and its degenerate form, the list.
Operations on container include:
- c = ao2_container_alloc(size, cmp_fn, hash_fn) allocate a container with desired size and default compare and hash function -The compare function returns an int, which can be 0 for not found, CMP_STOP to stop end a traversal, or CMP_MATCH if they are equal -The hash function returns an int. The hash function takes two argument, the object pointer and a flags field,
- ao2_find(c, arg, flags) returns zero or more element matching a given criteria (specified as arg). 'c' is the container pointer. Flags can be: OBJ_UNLINK - to remove the object, once found, from the container. OBJ_NODATA - don't return the object if found (no ref count change) OBJ_MULTIPLE - don't stop at first match (not fully implemented) OBJ_POINTER - if set, 'arg' is an object pointer, and a hashtable search will be done. If not, a traversal is done.
- ao2_callback(c, flags, fn, arg) apply fn(obj, arg) to all objects in the container. Similar to find. fn() can tell when to stop, and do anything with the object including unlinking it.
- c is the container;
- flags can be OBJ_UNLINK - to remove the object, once found, from the container. OBJ_NODATA - don't return the object if found (no ref count change) OBJ_MULTIPLE - don't stop at first match (not fully implemented) OBJ_POINTER - if set, 'arg' is an object pointer, and a hashtable search will be done. If not, a traversal is done through all the hashtable 'buckets'..
- fn is a func that returns int, and takes 3 args: (void *obj, void *arg, int flags); obj is an object arg is the same as arg passed into ao2_callback flags is the same as flags passed into ao2_callback fn returns: 0: no match, keep going CMP_STOP: stop search, no match CMP_MATCH: This object is matched.
Note that the entire operation is run with the container locked, so noone else can change its content while we work on it. However, we pay this with the fact that doing anything blocking in the callback keeps the container blocked. The mechanism is very flexible because the callback function fn() can do basically anything e.g. counting, deleting records, etc. possibly using arg to store the results.
- iterate on a container this is done with the following sequence
The difference with the callback is that the control on how to iterate is left to us.
- ao2_ref(c, -1) dropping a reference to a container destroys it, very simple!
Containers are ao2 objects themselves, and this is why their implementation is simple too.
Before declaring containers, we need to declare the types of the arguments passed to the constructor - in turn, this requires to define callback and hash functions and their arguments.