summaryrefslogtreecommitdiff
path: root/src/packet_cache.c
blob: 2e907b3cdfe7b886ed81a64975e5ddb1231bb438 (plain)
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
89
90
91
92
#include "packet_cache.h"

void nn_packet_cache_init(struct nn_packet_cache *cache, u32 size)
{
    al_array_init(cache->cache);
    al_array_reserve(cache->cache, size);
    cache->flush = (size > 0) ? size / 2 : 0;
    cache->disabled = false;
    nn_cond_init(&cache->cond);
    nn_mutex_init(&cache->mutex);
}

bool nn_packet_cache_available(struct nn_packet_cache *cache)
{
    nn_mutex_lock(&cache->mutex);
    return !cache->disabled;
}

void nn_packet_cache_send_packet(struct nn_packet_cache *cache, struct nn_packet *packet)
{
    al_assert(!cache->disabled);
    al_array_push(cache->cache, packet);
    bool flush = !packet || cache->cache.count >= cache->flush;
    if (flush && nn_cond_is_waiting(&cache->cond)) {
        nn_cond_signal(&cache->cond);
    }
}

void nn_packet_cache_flush(struct nn_packet_cache *cache)
{
    nn_mutex_lock(&cache->mutex);
    if (nn_cond_is_waiting(&cache->cond)) {
        nn_cond_signal(&cache->cond);
    }
    nn_mutex_unlock(&cache->mutex);
}

bool nn_packet_cache_wait(struct nn_packet_cache *cache, u32 *count)
{
    nn_mutex_lock(&cache->mutex);
    if (!cache->disabled && !cache->cache.count) {
        nn_cond_wait(&cache->cond, &cache->mutex);
    }
    // If there was an active wait before calling disable(), expected
    // behavior would be that wait() returns false.
    if (cache->disabled) {
        *count = 0;
        nn_mutex_unlock(&cache->mutex);
        return false;
    }
    *count = cache->cache.count;
    return true;
}

struct nn_packet *nn_packet_cache_at(struct nn_packet_cache *cache, u32 index)
{
    return al_array_at(cache->cache, index);
}

void nn_packet_cache_lock(struct nn_packet_cache *cache)
{
    nn_mutex_lock(&cache->mutex);
}

void nn_packet_cache_unlock(struct nn_packet_cache *cache)
{
    nn_mutex_unlock(&cache->mutex);
}

void nn_packet_cache_disable(struct nn_packet_cache *cache)
{
    nn_mutex_lock(&cache->mutex);
    cache->disabled = true;
    if (nn_cond_is_waiting(&cache->cond)) {
        nn_cond_signal(&cache->cond);
    }
    nn_mutex_unlock(&cache->mutex);
}

void nn_packet_cache_enable(struct nn_packet_cache *cache)
{
    nn_mutex_lock(&cache->mutex);
    cache->disabled = false;
    nn_mutex_unlock(&cache->mutex);
}

void nn_packet_cache_free(struct nn_packet_cache *cache)
{
    al_array_free(cache->cache);
    nn_mutex_destroy(&cache->mutex);
    nn_cond_destroy(&cache->cond);
}