aboutsummaryrefslogtreecommitdiff
path: root/doc/impl.md
blob: 626378da04d83cd33216a56d72863364bc0be0c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# Proone Implementation Note
## Dynamic Memory Allocation
POSIX compliant dynamic memory functions may return a valid pointer that can be
passed to `free()`(MALLOC(3)). Proone does not appreciate this inconsistency as
it has to be tolerant to memory allocation failure.

Consider following snippet.

```c
int *get_int_arr (size_t n) {
  int *ret = (int*)calloc(sizeof(int), n);

  if (ret == NULL) {
    abort();
  }

  for (size_t i = 0; i < n; i += 1) {
    ret[i] = i % INT_MAX;
  }

  return ret;
}
```

The behaviour of this code depends on whether `calloc()` returns a null or valid
pointer for zero-length allocation. To avoid mistakes like this one, the memory
allocation functions of the Proone framework(prefixed `prne_`) always returns
NULL for zero-length allocation. This way, the implementation is forced to infer
memory allocation failure from the parameter and the return value.

```c
  if (n > 0 && ret == NULL) {
```

All the memory allocated using the framework allocation functions(`prne_*()`)
must be freed with `prne_free()`.

## Resource Allocation Hook
One of the purposes of `prne_free()` and `prne_close()` is to facilitate the
implementation of a framework-level resource debugging(like MSVC macros) in the
future. This may be useful when use of Valgrind becomes too cumbersome. Another
is to keep a registry of the file descriptors for use in `prefork()` and
`atfork()` equivalent.

## Resource Allocation
### Transparent Structures

```c
prne_init_llist()
prne_free_llist()
```

Transparent structures must be initialised and deinitialised using the functions
provided.

The initialisation functions set the members of the structures to their default
values and prepares the structures for the deinitialisation calls. This is
normally done by zeroing the entire structure, but there are exceptions where
values other than zero are used for default values.

The deinitialisation functions are like "desctructors" in other languages. The
functions free any dynamically allocated members. For the structures that have
no dynamic members, the functions have no effect.

All initialisation and deinitialisation functions must be used to ensure that
the members added in the future are initialised/freed. Are guaranteed to take
one argument.

Deinitialised structures are not reusable. The structures must be reinitialised
after being deinitialised.

### Opaque Types

```c
prne_rnd_alloc_well512()
prne_alloc_resolv()
```

Opaque types, usually poly-morphed objects(class), are dynamically allocated by
"instantiation functions". Examples include `resolv` and `rnd`. The destructor
functions are provided upon successful instantiation. The underlying abstraction
layer is responsible for the invocation of the destructor functions.

### Dynamic Members

```c
prne_htbt_alloc_host_info()
prne_alloc_iobuf()
```

Some types have dynamically allocated members and the dynamic member allocation
functions are defined for dynamic members. Dynamic members can be freed by
calling the functions with zero for the size argument. Dynamic members are freed
by the deinitialisation functions.

### Ownership of Dynamically Resources
Some structures have the `ownership` flag member so their dynamic members,
especially large memory, can be used with other instances. If the structure has
the flag and its value is set, it means that the structure is the owner of the
dynamically allocated memory and is responsible for freeing it upon destruction
by the deinitialisation function. If the flag is unset, the deinitialisation
function will not free the dynamic members.

The flag can be used to form a chain of structures with the same dynamic
members. The flag can also be used to use data from .bss or .data as dynamic
members.