-
Notifications
You must be signed in to change notification settings - Fork 0
/
expire_list.c
143 lines (131 loc) · 4.12 KB
/
expire_list.c
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include <stdlib.h>
#include <assert.h>
#include "expire_list.h"
#ifdef DEBUG_EXPIRE_LIST
#include <stdio.h>
#define dprintf printf
#else
#define dprintf
#endif
texpire_list *expire_list_init(int (*cmp)(const void *v1, const void *v2)) {
texpire_list *list = malloc(sizeof(texpire_list));
assert(list != NULL);
list->items = NULL;
list->cmp = cmp;
return list;
}
void expire_list_free(texpire_list *list, void (*callback_free)(void *obj)) {
assert(list != NULL);
texpire_item *item = list->items;
while (item) {
if (callback_free)
(callback_free)(item->obj);
texpire_item *tmp = item;
item = item->next;
free(tmp);
}
free(list);
}
// inserts new object at appropriate position
void expire_list_add(texpire_list *list, void *obj, unsigned int expire_seconds) {
assert(list != NULL);
time_t t = time(NULL) + expire_seconds;
// find position of previous item ascending by t
texpire_item *prev = NULL;
for (texpire_item *item = list->items; item != NULL; item = item->next) {
if (item->t >= t)
break;
prev = item;
}
texpire_item *item = malloc(sizeof(texpire_item));
assert(item != NULL);
item->obj = obj;
item->t = t;
if (prev) {
item->next = prev->next;
prev->next = item;
} else {
// insert at beginning
item->next = list->items;
list->items = item;
}
}
// this is basically a delete followed by an add
// uses cmp function to find item if set (if cmp is unset, compares pointers directly)
void *expire_list_set(texpire_list *list, void *obj, unsigned int expire_seconds) {
time_t t = time(NULL) + expire_seconds;
// find item
texpire_item *prev = NULL;
texpire_item *item = list->items;
if (list->cmp == NULL) {
for (; item != NULL; item = item->next) {
if (item->obj == obj)
break;
prev = item;
}
} else {
for (; item != NULL; item = item->next) {
if (list->cmp(item->obj, obj) == 0)
break;
prev = item;
}
}
if (item) {
// something found, update timestamp
item->t = t;
// if it wasn't the first, we need to reposition it to the beginning
if (prev) {
// skip this item in list
prev->next = item->next;
// make this item the first
item->next = list->items;
list->items = item;
}
} else {
// nothing found, add it at the beginning
texpire_item *item = malloc(sizeof(texpire_item));
assert(item != NULL);
item->t = t;
item->obj = obj;
item->next = list->items;
list->items = item;
}
return item->obj;
}
void expire_list_run(texpire_list *list, void (*callback_expire)(void *obj)) {
time_t t = time(NULL);
dprintf("expiring objects with t <= %d\n", t);
while (list->items != NULL && t >= list->items->t) {
dprintf(" expiring object t=%d 0x%X\n", list->items->t, list->items->obj);
if (callback_expire)
callback_expire(list->items->obj);
texpire_item *tmp = list->items;
list->items = list->items->next;
free(tmp);
}
}
unsigned int expire_list_count(texpire_list *list) {
assert(list != NULL);
unsigned int ret = 0;
for (texpire_item *item = list->items; item != NULL; item = item->next)
ret ++;
return ret;
}
#ifdef DEBUG_EXPIRE_LIST
void expire_list_print(texpire_list *list, void (*callback_print)(void *obj)) {
if (list == NULL) {
dprintf("expire_list is null\n");
return;
}
dprintf("printing expire_list with %u items: -->\n", expire_list_count(list));
unsigned int i = 0;
for (texpire_item *item = list->items; item; item = item->next)
if (callback_print) {
dprintf("%u: %p t=%d next=%p obj=", i++, item, item->t, item->obj, item->next);
(callback_print)(item->obj);
} else {
dprintf("%u: %p t=%d next=%p obj=0x%X\n", i++, item, item->t, item->obj, item->next);
}
dprintf("<--\n");
}
#endif