docs/Writerside/topics/collection.h.md

Sat, 08 Feb 2025 20:38:05 +0100

author
Mike Becker <universe@uap-core.de>
date
Sat, 08 Feb 2025 20:38:05 +0100
branch
docs/3.1
changeset 1171
155bc3b0dcb3
parent 1146
151c057faf7c
permissions
-rw-r--r--

adds documentation for destructor functions and collections

also invented some new macros for the collection.h

relates to #451

# Collections

UCX defines common attributes for collections.
If you want to implement an own collection data type that uses the same features, you can use the
`CX_COLLECTION_BASE` macro at the beginning of your struct to roll out all members a usual UCX collection has.

This macro will embed a structure in your collection that can be accessed with the member name `collection`.

```c
struct my_fancy_collection_s {
    CX_COLLECTION_BASE; // adds a member named 'collection'
    struct my_collection_data_s *data;
};
```

> You can always look at the UCX list and map implementations if you need some inspiration.

## Base Attributes of a Collection

The following attributes are declared by the `CX_COLLECTION_BASE` macro:

| Attribute             | Description                                                                                                    |
|-----------------------|----------------------------------------------------------------------------------------------------------------|
| `allocator`           | The [allocator](allocator.h.md) that shall be used for the collection data.                                    |
| `cmpfunc`             | A function to [compare](compare.h.md) two elements.                                                            |
| `elem_size`           | The size of one element in bytes.                                                                              |
| `size`                | The size, meaning the number of elements, currently stored.                                                    |
| `simple_destructor`   | An optional simple [destructor function](allocator.h.md#destructor-functions).                                 |
| `advanced_destructor` | An optional advanced destructor function.                                                                      |
| `destructor_data`     | A pointer to the custom data that shall be passed to the advanced destructor.                                  |
| `store_pointer`       | A `bool` indicating whether this collection stores pointers instead of the element's data.                     |
| `sorted`              | A `bool` indicating whether the elements are currently guaranteed sorted with respect to the compare function. |

The attributes can be accessed directly via the `collection` member of your struct, or with the following convenience macros.

```C
cxCollectionSize(c)
cxCollectionElementSize(c)
cxCollectionStoresPointers(c)
cxCollectionSorted(c)
```

In each case the argument `c` is a pointer to your collection. The macro will then access the base data with `c->collection`.

For working with destructors, the following macros are defined:

```C
cxDefineDestructor(c, destr) 
cxDefineAdvancedDestructor(c, destr, data)

// use in your collection's implementation
cx_invoke_destructor(c, elem)
  
// the following two should not be used
cx_invoke_simple_destructor(c, elem) 
cx_invoke_advanced_destructor(c, elem) 
```

With `cxDefineDestructor()` you can assign a simple [destructor function](allocator.h.md#destructor-functions)
to an _instance_ of your collection.
Similarly, you can assign an advanced destructor with custom `data` by using `cxDefineAdvancedDestructor`.

Your collection _should_ be supporting destructors by invoking `cx_invoke_destructor()` whenever an element
is removed from your collection _without_ being returned to the caller.
This macro will invoke a simple destructor, if one is assigned, first, and then the advanced destructor (again, if assigned).

> Destructor functions are always invoked with a pointer to the element in your collection.
> If your collection is storing pointers (i.e. `cxCollectionStorePointers()` returns `true`)
> the `cx_invoke_destructor()` will make sure that the pointer to the element is dereferenced first,
> so that the destructor functions are _always_ invoked with pointer to the actual element.
{style="note"}

<seealso>
<category ref="apidoc">
<a href="https://ucx.sourceforge.io/api/collection_8h.html">collection.h</a>
</category>
</seealso>

mercurial