5G-MAG Reference Tools - MBMS Modem
MultichannelRingbuffer.cpp
Go to the documentation of this file.
1 // 5G-MAG Reference Tools
2 // MBMS Modem Process
3 //
4 // Copyright (C) 2021 Klaus Kühnhammer (Österreichische Rundfunksender GmbH & Co KG)
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU Affero General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU Affero General Public License for more details.
15 //
16 // You should have received a copy of the GNU Affero General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 //
19 
20 #include "MultichannelRingbuffer.h"
21 
22 #include <memory>
23 #include "spdlog/spdlog.h"
24 
26  : _size( size )
27  , _channels( channels )
28  , _used( 0 )
29  , _head( 0 )
30 {
31  for (auto ch = 0; ch < _channels; ch++) {
32  auto buf = (char*)malloc(_size);
33  if (buf == nullptr) {
34  throw "Could not allocate memory";
35  }
36  _buffers.push_back(buf);
37  }
38  spdlog::debug("Created {}-channel ringbuffer with size {}", _channels, _size );
39 }
40 
42 {
43  for (auto buffer : _buffers) {
44  if (buffer) free(buffer);
45  }
46 }
47 
48 auto MultichannelRingbuffer::write_head(size_t* writeable) -> std::vector<void*>
49 {
50 // _mutex.lock();
51  std::lock_guard<std::mutex> lock(_mutex);
52  std::vector<void*> buffers(_channels, nullptr);
53  if (_size == _used) {
54  *writeable = 0;
55  } else {
56  auto tail = (_head + _used) % _size;
57  if (tail < _head) {
58  *writeable = _head - tail;
59  } else {
60  *writeable = _size - tail;
61  }
62  for (auto ch = 0; ch < _channels; ch++) {
63  buffers[ch] = (void*)(_buffers[ch] + tail);
64  }
65  }
66 
67  return buffers;
68 }
69 
70 auto MultichannelRingbuffer::commit(size_t written) -> void
71 {
72  assert(written >= 0);
73  assert(written <= free_size());
74  std::lock_guard<std::mutex> lock(_mutex);
75  _used += written;
76 // _mutex.unlock();
77 }
78 
79 auto MultichannelRingbuffer::read(std::vector<char*> dest, size_t size) -> void
80 {
81  assert(dest.size() >= _channels);
82  assert(size <= used_size());
83  assert(size >= 0);
84 
85  std::lock_guard<std::mutex> lock(_mutex);
86  auto end = (_head + size) % _size;
87 
88  if (end <= _head) {
89  auto first_part = _size - _head;
90  auto second_part = size - first_part;
91  for (auto ch = 0; ch < _channels; ch++) {
92  memcpy(dest[ch], _buffers[ch] + _head, first_part);
93  memcpy(dest[ch] + first_part, _buffers[ch], second_part);
94  }
95  } else {
96  for (auto ch = 0; ch < _channels; ch++) {
97  memcpy(dest[ch], _buffers[ch] + _head, size);
98  }
99  }
100  _head = (_head + size) % _size;
101  _used -= size;
102 }
void read(std::vector< char * > dest, size_t bytes)
std::vector< char * > _buffers
std::vector< void * > write_head(size_t *writeable)
MultichannelRingbuffer(size_t size, size_t channels)