Repository navigation
Expand file tree
/
Copy pathDSPConfig.c
More file actions
77 lines (68 loc) · 2.31 KB
/
Copy pathDSPConfig.c
File metadata and controls
77 lines (68 loc) · 2.31 KB
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
#include "DSPConfig.h"
#include <mach/mach_time.h>
#include <stdatomic.h>
#include <stdlib.h>
#include <string.h>
typedef struct PBConfigNode {
PBDSPConfig config;
uint64_t publishedAt;
struct PBConfigNode *next;
} PBConfigNode;
struct PBDSPConfigStore {
_Atomic(PBConfigNode *) current;
PBConfigNode *retired; // newest first; only touched by the publishing thread
};
static uint64_t nanosPerTick(void) {
static mach_timebase_info_data_t info;
if (info.denom == 0) mach_timebase_info(&info);
return info.numer / info.denom;
}
PBDSPConfigStore *PBDSPConfigStoreCreate(void) {
PBDSPConfigStore *store = calloc(1, sizeof(PBDSPConfigStore));
if (store == NULL) return NULL;
atomic_init(&store->current, NULL);
return store;
}
void PBDSPConfigStoreDestroy(PBDSPConfigStore *store) {
if (store == NULL) return;
PBConfigNode *node = store->retired;
while (node != NULL) {
PBConfigNode *next = node->next;
free(node);
node = next;
}
free(store);
}
void PBDSPConfigStorePublish(PBDSPConfigStore *store, const PBDSPConfig *config) {
if (store == NULL || config == NULL) return;
PBConfigNode *node = malloc(sizeof(PBConfigNode));
if (node == NULL) return;
memcpy(&node->config, config, sizeof(PBDSPConfig));
node->publishedAt = mach_absolute_time();
node->next = store->retired;
store->retired = node;
atomic_store_explicit(&store->current, node, memory_order_release);
// Free everything older than the grace window, keeping the current node.
const uint64_t graceTicks = 2000000000ULL / nanosPerTick();
PBConfigNode *keep = node;
PBConfigNode *cursor = node->next;
while (cursor != NULL) {
PBConfigNode *next = cursor->next;
if (node->publishedAt - cursor->publishedAt > graceTicks) {
keep->next = NULL;
while (cursor != NULL) {
PBConfigNode *n = cursor->next;
free(cursor);
cursor = n;
}
break;
}
keep = cursor;
cursor = next;
}
}
const PBDSPConfig *PBDSPConfigStoreLoad(const PBDSPConfigStore *store) {
if (store == NULL) return NULL;
PBConfigNode *node = atomic_load_explicit(&store->current, memory_order_acquire);
return node == NULL ? NULL : &node->config;
}