Skip to content

Commit c3ffc39

Browse files
committed
Offer an API for both stack and map to set a data dtor to be called for autofree data.
1 parent de57f85 commit c3ffc39

File tree

7 files changed

+63
-8
lines changed

7 files changed

+63
-8
lines changed

Lib/map.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct _map {
2525
int table_size;
2626
int size;
2727
map_elem *data;
28+
map_dtor dtor;
2829
};
2930

3031
static unsigned long crc32(const unsigned char *s, unsigned int len);
@@ -205,7 +206,11 @@ static void clear_elem(map_t *m, const int idx) {
205206
m->data[idx].key_needs_free = false;
206207

207208
if (m->data[idx].val_needs_free) {
208-
memhook._free((void *)m->data[idx].data);
209+
if (m->dtor) {
210+
m->dtor(m->data[idx].data);
211+
} else {
212+
memhook._free((void *)m->data[idx].data);
213+
}
209214
}
210215
m->data[idx].data = NULL;
211216
m->data[idx].val_needs_free = false;
@@ -324,6 +329,7 @@ map_ret_code map_clear(map_t *m) {
324329
clear_elem(m, i);
325330
}
326331
}
332+
m->dtor = NULL;
327333
return MAP_OK;
328334
}
329335

@@ -342,3 +348,9 @@ int map_length(const map_t *m) {
342348
MOD_ASSERT(m, "NULL map.", MAP_WRONG_PARAM);
343349
return m->size;
344350
}
351+
352+
map_ret_code map_set_dtor(map_t *m, map_dtor fn) {
353+
MOD_ASSERT(m, "NULL map.", MAP_WRONG_PARAM);
354+
m->dtor = fn;
355+
return MAP_OK;
356+
}

Lib/public/module/map.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ typedef enum {
1616
/* Callback for map_iterate */
1717
typedef map_ret_code (*map_cb)(void *, void *);
1818

19+
/* Fn for map_set_dtor */
20+
typedef map_ret_code (*map_dtor)(void *);
21+
1922
/* Incomplete struct declaration for hashmap */
2023
typedef struct _map map_t;
2124

@@ -32,6 +35,7 @@ _public_ map_ret_code map_remove(map_t *m, const char *key);
3235
_public_ map_ret_code map_clear(map_t *m);
3336
_public_ map_ret_code map_free(map_t *m);
3437
_public_ int map_length(const map_t *m);
38+
_public_ map_ret_code map_set_dtor(map_t *m, map_dtor fn);
3539

3640
#ifdef __cplusplus
3741
}

Lib/public/module/stack.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ typedef enum {
1313
} stack_ret_code;
1414

1515
/* Callback for stack_iterate */
16-
typedef stack_ret_code (*stack_cb)(void *, void *);
16+
typedef stack_ret_code(*stack_cb)(void *, void *);
17+
18+
/* Fn for stack_set_dtor */
19+
typedef stack_ret_code(*stack_dtor)(void *);
1720

1821
/* Incomplete struct declaration for stack */
1922
typedef struct _stack stack_t;
@@ -30,6 +33,7 @@ _public_ void *stack_peek(const stack_t *s);
3033
_public_ stack_ret_code stack_clear(stack_t *s);
3134
_public_ stack_ret_code stack_free(stack_t *s);
3235
_public_ int stack_length(const stack_t *s);
36+
_public_ stack_ret_code stack_set_dtor(stack_t *s, stack_dtor fn);
3337

3438
#ifdef __cplusplus
3539
}

Lib/stack.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ typedef struct _elem {
88

99
struct _stack {
1010
int len;
11+
stack_dtor dtor;
1112
stack_elem *data;
1213
};
1314

@@ -74,9 +75,14 @@ stack_ret_code stack_clear(stack_t *s) {
7475
const bool autofree = elem->autofree;
7576
void *data = stack_pop(s);
7677
if (autofree) {
77-
memhook._free(data);
78+
if (s->dtor) {
79+
s->dtor(data);
80+
} else {
81+
memhook._free(data);
82+
}
7883
}
7984
}
85+
s->dtor = NULL;
8086
return STACK_OK;
8187
}
8288

@@ -90,6 +96,11 @@ stack_ret_code stack_free(stack_t *s) {
9096

9197
int stack_length(const stack_t *s) {
9298
MOD_ASSERT(s, "NULL stack.", STACK_WRONG_PARAM);
93-
9499
return s->len;
95100
}
101+
102+
stack_ret_code stack_set_dtor(stack_t *s, stack_dtor fn) {
103+
MOD_ASSERT(s, "NULL stack.", STACK_WRONG_PARAM);
104+
s->dtor = fn;
105+
return STACK_OK;
106+
}

TODO.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ module_ref should then return a new self_t* object, add it to a stack in module.
3737
- [x] Add _clear function
3838
- [x] Add tests!
3939
- [x] Update doc!
40+
- [x] Offer a stack_set_dtor() API to offer a callback to free each item when autofree is true
4041

4142
### Map API
4243
- [x] Add _clear function
4344
- [x] Add tests!
4445
- [x] Fix issue in map_new if m->data calloc fails: map object was not memsetted to 0; it would lead to a crash when map_free was called
4546
- [x] Update doc!
47+
- [x] Offer a map_set_dtor() to offer a callback to free each item when autofree is true
4648

4749
### Fix
4850
- [x] Actually honor current module's callback when flushing pubsub messages
@@ -54,7 +56,6 @@ module_ref should then return a new self_t* object, add it to a stack in module.
5456

5557
## 4.1.0
5658
- [ ] PoisonPill message to automatically stop another module?
57-
- [ ] Expose a queue and use it for internally storing each module's fds
5859

5960
## Ideas
6061
- [ ] Let contexts talk together? Eg: broadcast(msg, bool global) to send a message to all modules in every context; module_publish message in another context? etc etc

docs/src/map.rst

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ Structures
2424
2525
/* Callback for map_iterate */
2626
typedef map_ret_code (*map_cb)(void *, void *);
27+
28+
/* Fn for map_set_dtor */
29+
typedef map_ret_code (*map_dtor)(void *);
2730
2831
/* Incomplete struct declaration for hashmap */
2932
typedef struct _map map_t;
@@ -52,7 +55,7 @@ Where not specified, these functions return a map_ret_code.
5255

5356
.. c:function:: map_put(m, key, val, dupkey, autofree)
5457
55-
Put a value inside hashmap. Note that if dupkey is true, key will be strdupped; it will also be automatically freed upon deletion.
58+
Put a value inside hashmap. Note that if dupkey is true, key will be strdupped and its lifetime will be managed by libmodule.
5659

5760
:param m: pointer to map_t
5861
:param key: key for this value
@@ -96,7 +99,7 @@ Where not specified, these functions return a map_ret_code.
9699

97100
.. c:function:: map_clear(m)
98101
99-
Clears a map object by deleting any object inside map, and eventually freeing it too if marked with autofree.
102+
Clears a map object by deleting any object inside map, and eventually freeing it too if marked with autofree. Note that map dtor (if any) will be set to NULL too.
100103

101104
:param s: pointer to map_t
102105
:type s: :c:type:`map_t *`
@@ -115,3 +118,12 @@ Where not specified, these functions return a map_ret_code.
115118
:param m: pointer to map_t
116119
:type m: :c:type:`map_t *`
117120
:returns: map length or a map_ret_code if any error happens (map_t is null).
121+
122+
.. c:function:: map_set_dtor(m, fn)
123+
124+
Set a function to be called upon data deletion for autofree elements.
125+
126+
:param m: pointer to map_t
127+
:param fn: pointer dtor callback
128+
:type m: :c:type:`map_t *`
129+
:type fn: :c:type:`map_dtor`

docs/src/stack.rst

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ Structures
2323
2424
/* Callback for stack_iterate */
2525
typedef stack_ret_code (*stack_cb)(void *, void *);
26+
27+
/* Fn for stack_set_dtor */
28+
typedef stack_ret_code(*stack_dtor)(void *);
2629
2730
/* Incomplete struct declaration for stack */
2831
typedef struct _stack stack_t;
@@ -78,7 +81,7 @@ Where not specified, these functions return a stack_ret_code.
7881

7982
.. c:function:: stack_clear(s)
8083
81-
Clears a stack object by deleting any object inside stack, and eventually freeing it too if marked with autofree.
84+
Clears a stack object by deleting any object inside stack, and eventually freeing it too if marked with autofree. Note that stack dtor (if any) will be set to NULL too.
8285

8386
:param s: pointer to stack_t
8487
:type s: :c:type:`stack_t *`
@@ -98,3 +101,11 @@ Where not specified, these functions return a stack_ret_code.
98101
:type s: :c:type:`stack_t *`
99102
:returns: stack length or a stack_ret_code if any error happens (stack_t is null).
100103

104+
.. c:function:: stack_set_dtor(s, fn)
105+
106+
Set a function to be called upon data deletion for autofree elements.
107+
108+
:param s: pointer to stack_t
109+
:param fn: pointer dtor callback
110+
:type s: :c:type:`stack_t *`
111+
:type fn: :c:type:`stack_dtor`

0 commit comments

Comments
 (0)