-
Notifications
You must be signed in to change notification settings - Fork 82
/
Copy pathcmap.h
83 lines (69 loc) · 2.57 KB
/
cmap.h
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
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "rcu.h"
#include "util.h"
/* Concurrent cmap.
* It supports multiple concurrent readers and a single concurrent writer.
* To iterate, the user needs to acquire a "cmap state" (snapshot).
*/
struct cmap_node {
struct cmap_node *next; /* Next node with same hash. */
uint32_t hash;
};
/* Used for going over all cmap nodes */
struct cmap_cursor {
struct cmap_node *node; /* Pointer to cmap_node */
struct cmap_node *next; /* Pointer to cmap_node */
size_t entry_idx; /* Current entry */
bool accross_entries; /* Hold cursor accross cmap entries */
};
/* Map state (snapshot), must be acquired before cmap iteration, and released
* afterwards.
*/
struct cmap_state {
struct rcu *p;
};
/* Concurrent hash cmap. */
struct cmap {
struct cmap_state *impl;
};
/* Initialization. */
void cmap_init(struct cmap *);
void cmap_destroy(struct cmap *);
/* Counters. */
size_t cmap_size(const struct cmap *);
double cmap_utilization(const struct cmap *cmap);
/* Insertion and deletion. Return the current count after the operation. */
size_t cmap_insert(struct cmap *, struct cmap_node *, uint32_t hash);
size_t cmap_remove(struct cmap *, struct cmap_node *);
/* Acquire/release cmap concurrent state. Use with iteration macros.
* Each acquired state must be released. */
struct cmap_state cmap_state_acquire(struct cmap *cmap);
void cmap_state_release(struct cmap_state state);
/* Iteration macros. Usage example:
*
* struct {
* struct cmap_node node;
* int value;
* } *data;
* struct cmap_state *cmap_state = cmap_state_acquire(&cmap);
* MAP_FOREACH(data, node, cmap_state) {
* ...
* }
* cmap_state_release(cmap_state);
*/
#define MAP_FOREACH(NODE, MEMBER, STATE) \
MAP_FOREACH__(NODE, MEMBER, MAP, cmap_start__(STATE), STATE)
#define MAP_FOREACH_WITH_HASH(NODE, MEMBER, HASH, STATE) \
MAP_FOREACH__(NODE, MEMBER, MAP, cmap_find__(STATE, HASH), STATE)
/* Ieration, private methods. Use iteration macros instead */
struct cmap_cursor cmap_start__(struct cmap_state state);
struct cmap_cursor cmap_find__(struct cmap_state state, uint32_t hash);
void cmap_next__(struct cmap_state state, struct cmap_cursor *cursor);
#define MAP_FOREACH__(NODE, MEMBER, MAP, START, STATE) \
for (struct cmap_cursor cursor_ = START; \
(cursor_.node ? (INIT_CONTAINER(NODE, cursor_.node, MEMBER), true) \
: false); \
cmap_next__(STATE, &cursor_))