-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpqueue.hpp
120 lines (87 loc) · 4.34 KB
/
pqueue.hpp
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#ifndef PQUEUE_HEADER
#define PQUEUE_HEADER
#include <deque>
#include <cstring>
#include "packet.hpp"
// Шаблон класса, описывающего очередь пакетов
// Параметры шаблона:
// MAX_LEN - максимальная длина данных в пакете
// MAX_CNT - максимальное количество пакетов в очереди
// MAX_SIZE - максимальный общий объём данных всех пакетов в очереди
template <const size_t MAX_LEN, const size_t MAX_CNT, const size_t MAX_SIZE>
class Pqueue {
public:
// Конструктор по умолчанию
Pqueue() : total_(0) {}
// Получение количества пакетов в очереди
const size_t get_packet_count() const { return fifo_.size(); }
// Добавление пакета в очередь
bool push(const DataType* data, const size_t data_count,
const size_t packet_id);
// Извлечение пакета из очереди
bool pop(DataType* buffer, const size_t buffer_size,
size_t& data_count, size_t& packet_id);
private:
// Макимальная длина данных в пакете
static const size_t max_packet_length_ = MAX_LEN;
// Максимальное количество пакетов в очереди
static const size_t max_packet_count_ = MAX_CNT;
// Максимальный общий объём данных всех пакетов в очереди
static const size_t max_queue_size_ = MAX_SIZE;
// Контейнер пакетов
std::deque<Packet> fifo_;
// Счётчик общего объёма данных всех пакетов в очереди
size_t total_;
};
// push - Добавление пакета в очередь
// data: указатель на входные данные
// data_count: объём входных данных
// packet_id: идентификатор пакета
template <const size_t L, const size_t C, const size_t S>
bool Pqueue<L, C, S>::push(const DataType* data, const size_t data_count,
const size_t packet_id)
{
// Проверка, не превышен ли какой-нибудь лимит
if (data_count > max_packet_length_ ||
get_packet_count() >= max_packet_count_ ||
total_ + data_count > max_queue_size_)
return false;
// Создаём в конце очереди новый пакет на основе массива данных
fifo_.emplace_back(data, data_count, packet_id);
// Увеличиваем счётчик размера всех данных в очереди
total_ += data_count;
return true;
}
// Извлечение пакета из очереди
// buffer: указатель на буфер для копирования данных пакета
// buffer_size: размер буфера
// data_count: ссылка на объём данных, полученных из пакета
// packet_id: ссылка на идентификатор пакета
// Возвращает true в случае извлечения данных из пакета,
// false - когда очередь пуста
template <const size_t L, const size_t C, const size_t S>
bool Pqueue<L, C, S>::pop(DataType* buffer, const size_t buffer_size,
size_t& data_count, size_t& packet_id)
{
// Проверяем, не пуста ли очередь
if (! get_packet_count())
return false;
// Ярлык на первый пакет в очереди
const Packet pkt = fifo_.front();
// Получаем идентификатор пакета
packet_id = pkt.get_id();
// Узнаём размер данных в пакете
const size_t packet_size = pkt.get_size();
// Определяем сколько данных надо скопировать из пакета в буфер,
// в зависимости от того, превышает ли объём данных в пакете
// размер переданного буфера
data_count = (buffer_size < packet_size) ? buffer_size : packet_size;
// Копируем данные из пакета в буфер
std::memcpy(buffer, pkt.get_data(), data_count);
// Уменьшаем счётчик всех данных в очереди
total_ -= packet_size;
// Удаляем из очереди первый пакет
fifo_.pop_front();
return true;
}
#endif