1 # Collections |
1 # Collections |
2 |
2 |
3 <warning> |
3 UCX defines common attributes for collections. |
4 Outdated - Rewrite! |
|
5 </warning> |
|
6 |
|
7 Collections in UCX 3 have several common features. |
|
8 If you want to implement an own collection data type that uses the same features, you can use the |
4 If you want to implement an own collection data type that uses the same features, you can use the |
9 `CX_COLLECTION_BASE` macro at the beginning of your struct to roll out all members a usual UCX collection has. |
5 `CX_COLLECTION_BASE` macro at the beginning of your struct to roll out all members a usual UCX collection has. |
|
6 |
|
7 This macro will embed a structure in your collection that can be accessed with the member name `collection`. |
|
8 |
10 ```c |
9 ```c |
11 struct my_fancy_collection_s { |
10 struct my_fancy_collection_s { |
12 CX_COLLECTION_BASE; |
11 CX_COLLECTION_BASE; // adds a member named 'collection' |
13 struct my_collection_data_s *data; |
12 struct my_collection_data_s *data; |
14 }; |
13 }; |
15 ``` |
14 ``` |
16 Based on this structure, this header provides some convenience macros for invoking the destructor functions |
|
17 that are part of the basic collection members. |
|
18 The idea of having destructor functions within a collection is that you can destroy the collection _and_ the |
|
19 contents with one single function call. |
|
20 When you are implementing a collection, you are responsible for invoking the destructors at the right places, e.g. |
|
21 when removing (and deleting) elements in the collection, clearing the collection, or - the most prominent case - |
|
22 destroying the collection. |
|
23 |
15 |
24 You can always look at the UCX list and map implementations if you need some inspiration. |
16 > You can always look at the UCX list and map implementations if you need some inspiration. |
|
17 |
|
18 ## Base Attributes of a Collection |
|
19 |
|
20 The following attributes are declared by the `CX_COLLECTION_BASE` macro: |
|
21 |
|
22 | Attribute | Description | |
|
23 |-----------------------|----------------------------------------------------------------------------------------------------------------| |
|
24 | `allocator` | The [allocator](allocator.h.md) that shall be used for the collection data. | |
|
25 | `cmpfunc` | A function to [compare](compare.h.md) two elements. | |
|
26 | `elem_size` | The size of one element in bytes. | |
|
27 | `size` | The size, meaning the number of elements, currently stored. | |
|
28 | `simple_destructor` | An optional simple [destructor function](allocator.h.md#destructor-functions). | |
|
29 | `advanced_destructor` | An optional advanced destructor function. | |
|
30 | `destructor_data` | A pointer to the custom data that shall be passed to the advanced destructor. | |
|
31 | `store_pointer` | A `bool` indicating whether this collection stores pointers instead of the element's data. | |
|
32 | `sorted` | A `bool` indicating whether the elements are currently guaranteed sorted with respect to the compare function. | |
|
33 |
|
34 The attributes can be accessed directly via the `collection` member of your struct, or with the following convenience macros. |
|
35 |
|
36 ```C |
|
37 cxCollectionSize(c) |
|
38 cxCollectionElementSize(c) |
|
39 cxCollectionStoresPointers(c) |
|
40 cxCollectionSorted(c) |
|
41 ``` |
|
42 |
|
43 In each case the argument `c` is a pointer to your collection. The macro will then access the base data with `c->collection`. |
|
44 |
|
45 For working with destructors, the following macros are defined: |
|
46 |
|
47 ```C |
|
48 cxDefineDestructor(c, destr) |
|
49 cxDefineAdvancedDestructor(c, destr, data) |
|
50 |
|
51 // use in your collection's implementation |
|
52 cx_invoke_destructor(c, elem) |
|
53 |
|
54 // the following two should not be used |
|
55 cx_invoke_simple_destructor(c, elem) |
|
56 cx_invoke_advanced_destructor(c, elem) |
|
57 ``` |
|
58 |
|
59 With `cxDefineDestructor()` you can assign a simple [destructor function](allocator.h.md#destructor-functions) |
|
60 to an _instance_ of your collection. |
|
61 Similarly, you can assign an advanced destructor with custom `data` by using `cxDefineAdvancedDestructor`. |
|
62 |
|
63 Your collection _should_ be supporting destructors by invoking `cx_invoke_destructor()` whenever an element |
|
64 is removed from your collection _without_ being returned to the caller. |
|
65 This macro will invoke a simple destructor, if one is assigned, first, and then the advanced destructor (again, if assigned). |
|
66 |
|
67 > Destructor functions are always invoked with a pointer to the element in your collection. |
|
68 > If your collection is storing pointers (i.e. `cxCollectionStorePointers()` returns `true`) |
|
69 > the `cx_invoke_destructor()` will make sure that the pointer to the element is dereferenced first, |
|
70 > so that the destructor functions are _always_ invoked with pointer to the actual element. |
|
71 {style="note"} |
|
72 |
|
73 <seealso> |
|
74 <category ref="apidoc"> |
|
75 <a href="https://ucx.sourceforge.io/api/collection_8h.html">collection.h</a> |
|
76 </category> |
|
77 </seealso> |