-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcaching.c
88 lines (72 loc) · 2.07 KB
/
caching.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
#include <pthread.h>
#include <stdatomic.h>
#include <stdbool.h>
#include "caching.h"
#include "backend.h"
static bool first = true;
static pthread_t tid;
static bool thread_done = false;
static PInfo *thread_pinfos = NULL;
static size_t thread_len = 0;
static PInfo *cached_pinfos = NULL;
static size_t cached_len = 0;
PInfo *parse_proc_get_cached(size_t *len)
{
atomic_thread_fence(memory_order_acquire); // get updates from worker thread
if (thread_done) { // finished generating
if (cached_pinfos != thread_pinfos) { // but haven't claimed the results
free_parsed(cached_pinfos);
cached_pinfos = thread_pinfos;
cached_len = thread_len;
}
}
if (len != NULL) {
*len = cached_len;
}
return copy_parsed(cached_pinfos, cached_len);
}
PInfo* cache_proc(PInfo *pinfos, size_t len)
{ // makes a copy of pinfos - the caller still owns and is responsible for freeing the pinfos they passed in
free_parsed(cached_pinfos);
cached_pinfos = copy_parsed(pinfos, len);
cached_len = len;
return cached_pinfos;
}
static void* thread_parse_proc(__attribute__((unused)) void *data)
{
atomic_thread_fence(memory_order_acquire); // send updates back to main thread
thread_pinfos = parse_proc(&thread_len);
thread_done = true;
atomic_thread_fence(memory_order_release); // send updates back to main thread
return NULL;
}
int queue_cache_update()
{
if (!first) {
atomic_thread_fence(memory_order_acquire); // get updates from worker thread
if (thread_done) {
pthread_join(tid, NULL);
if (cached_pinfos != thread_pinfos) {
free_parsed(cached_pinfos);
cached_pinfos = thread_pinfos;
cached_len = thread_len;
}
} else {
return -1;
}
} else {
first = false;
}
thread_done = false;
pthread_create(&tid, NULL, thread_parse_proc, NULL);
return 0;
}
void deinit_cache() // to be called only when the cache will never be used again, at program exit
{
free_parsed(cached_pinfos);
atomic_thread_fence(memory_order_acquire); // get updates from worker thread
if (!first && !thread_done) {
pthread_join(tid, NULL);
free_parsed(thread_pinfos);
}
}