forked from ablevm/libable
-
Notifications
You must be signed in to change notification settings - Fork 0
/
edge.c
78 lines (73 loc) · 1.39 KB
/
edge.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
#include <stdatomic.h>
#include "edge.h"
#include <string.h>
int
able_edge_clip(able_edge_t *edge, void *data, size_t size) {
if (atomic_load(&edge->rc) > 0)
return 1;
int v;
v = 0;
while (!atomic_compare_exchange_weak(&edge->sl, &v, -1)) {
if (v == 1)
return -1;
v = 0;
}
if (atomic_load(&edge->rc) > 0) {
atomic_store(&edge->sl, 0);
return 1;
}
edge->s = data;
edge->sc = size;
atomic_store(&edge->sl, 0);
return 0;
}
size_t
able_edge_recv(able_edge_t *edge) {
return atomic_exchange(&edge->rc, 0);
}
int
able_edge_send_long(able_edge_t *edge, size_t size, void **data) {
if (size == 0)
return 1;
int v;
v = 0;
while (!atomic_compare_exchange_weak(&edge->sl, &v, -1)) {
if (v == 1)
return -1;
v = 0;
}
if (edge->sc < size) {
atomic_store(&edge->sl, 0);
return -2;
}
atomic_store(&edge->sl, 1);
edge->tc = size;
*data = edge->s;
return 0;
}
int
able_edge_send_done(able_edge_t *edge, size_t size) {
if (size == 0) {
atomic_store(&edge->sl, 0);
return 0;
}
if (size > edge->tc) {
atomic_store(&edge->sl, 0);
return 2;
}
edge->s += size;
edge->sc -= size;
atomic_fetch_add(&edge->rc, size);
atomic_store(&edge->sl, 0);
return 0;
}
int
able_edge_send(able_edge_t *edge, const void *data, size_t size) {
void *m;
int y;
y = able_edge_send_long(edge, size, &m);
if (y != 0)
return y;
memcpy(m, data, size);
return able_edge_send_done(edge, size);
}