skip to content
==> tests/chan.c <==
1/* Order, growth, bounds, timeouts, disconnects and drops, with threads. */
2#include "mesh/chan.h"
3#include "mesh/check.h"
4
5#include <pthread.h>
6
7static int dropped;
8static void count_drop(void *item) { dropped += *(int *)item; }
9
10static void *producer(void *arg) {
11    mesh_chan *c = arg;
12    for (int i = 0; i < 10000; i++) mesh_chan_send(c, &i);
13    mesh_chan_drop_sender(c);
14    mesh_chan_release(c);
15    return NULL;
16}
17
18int main(void) {
19    mesh_chan *c = mesh_chan_new(sizeof(int), 0, NULL);
20    for (int i = 0; i < 100; i++) CHECK_I(mesh_chan_send(c, &i), MESH_CHAN_OK);
21    CHECK_U(mesh_chan_len(c), 100);
22    int v = -1, ok = 1;
23    for (int i = 0; i < 100; i++) ok &= mesh_chan_try_recv(c, &v) == MESH_CHAN_OK && v == i;
24    CHECK(ok);
25    CHECK_I(mesh_chan_try_recv(c, &v), MESH_CHAN_EMPTY);
26    int64_t t0 = mesh_mono_ms();
27    CHECK_I(mesh_chan_recv(c, &v, 50), MESH_CHAN_TIMEOUT);
28    int64_t dt = mesh_mono_ms() - t0;
29    CHECK(dt >= 45 && dt < 1000);
30    /* A producer thread: every message, in order, then disconnected. */
31    mesh_chan_retain(c);
32    mesh_chan_add_sender(c); /* the thread's */
33    pthread_t th;
34    pthread_create(&th, NULL, producer, c);
35    mesh_chan_drop_sender(c); /* ours: only the thread's remains */
36    long sum = 0;
37    int n = 0, last = -1, ordered = 1;
38    while (mesh_chan_recv(c, &v, -1) == MESH_CHAN_OK) { ordered &= v == last + 1; last = v; sum += v; n++; }
39    pthread_join(th, NULL);
40    CHECK(ordered);
41    CHECK_I(n, 10000);
42    CHECK_I(sum, 49995000L);
43    CHECK_I(mesh_chan_try_recv(c, &v), MESH_CHAN_CLOSED);
44    mesh_chan_release(c);
45
46    /* Bounded: full; the receiver gone: closed, and queued messages dropped. */
47    mesh_chan *b = mesh_chan_new(sizeof(int), 2, count_drop);
48    int one = 1, two = 2, three = 3;
49    CHECK_I(mesh_chan_try_send(b, &one), MESH_CHAN_OK);
50    CHECK_I(mesh_chan_try_send(b, &two), MESH_CHAN_OK);
51    CHECK_I(mesh_chan_try_send(b, &three), MESH_CHAN_FULL);
52    mesh_chan_close_rx(b);
53    CHECK_I(dropped, 3);
54    CHECK_I(mesh_chan_try_send(b, &three), MESH_CHAN_CLOSED);
55    mesh_chan_release(b);
56
57    /* Released with messages queued: they are dropped. */
58    dropped = 0;
59    mesh_chan *d = mesh_chan_new(sizeof(int), 0, count_drop);
60    mesh_chan_send(d, &two);
61    mesh_chan_send(d, &three);
62    mesh_chan_release(d);
63    CHECK_I(dropped, 5);
64    return mesh_check_done();
65}