Falcon
Toggle main menu visibility
Loading...
Searching...
No Matches
streamports.hpp
1
// ---------------------------------------------------------------------
2
// This file is part of falcon-core.
3
//
4
// Copyright (C) 2015, 2016, 2017 Neuro-Electronics Research Flanders
5
//
6
// Falcon-server is free software: you can redistribute it and/or modify
7
// it under the terms of the GNU 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
// Falcon-server 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 General Public License for more details.
15
//
16
// You should have received a copy of the GNU General Public License
17
// along with falcon-core. If not, see <http://www.gnu.org/licenses/>.
18
// ---------------------------------------------------------------------
19
20
#pragma once
21
22
#include <memory>
23
#include <set>
24
#include <string>
25
#include <vector>
26
27
#include "istreamports.hpp"
28
#include "utilities/math_numeric.hpp"
29
30
struct
RingBufferStatus
{
31
uint64_t read;
32
uint64_t backlog;
33
bool
alive;
34
};
35
36
// forward declarations
37
template
<
typename
DATATYPE>
38
class
SlotIn
;
39
template
<
typename
DATATYPE>
40
class
PortOut
;
41
template
<
typename
DATATYPE>
42
class
PortIn
;
43
int
IdentifyNextSlot(
int
slot_request,
int
connected_slot_number,
bool
allow_multi_connect,
44
const
PortPolicy
& policy);
45
46
template
<
typename
DATATYPE>
47
class
SlotOut :
public
ISlotOut {
48
friend
class
PortOut
<DATATYPE>;
49
50
public
:
51
SlotOut(
PortOut<DATATYPE>
* parent,
const
SlotAddress
& address,
52
const
typename
DATATYPE::Parameters& parameters)
53
: ISlotOut(parent, address), streaminfo_(parameters), ringbuffer_serial_number_(0) {}
54
55
// public interface
56
typename
DATATYPE::Data* ClaimData(
bool
clear);
57
std::vector<typename DATATYPE::Data*> ClaimDataN(uint64_t n,
bool
clear);
58
void
PublishData();
59
60
virtual
StreamInfo<DATATYPE>
& streaminfo() {
return
streaminfo_; }
61
const
typename
DATATYPE::Data& prototype()
const
{
62
return
streaminfo_.template getDataPrototype<typename DATATYPE::Data>();
63
}
64
uint64_t nitems_produced()
const
;
65
66
protected
:
67
// called by SlotIn<DATATYPE>
68
virtual
typename
DATATYPE::Data* DataAt(int64_t sequence)
const
{
69
return
ringbuffer_->Get(sequence);
70
}
71
72
void
CreateRingBuffer(
int
buffer_size, WaitStrategy wait_strategy);
73
void
Unlock();
74
75
RingBatch* next_batch(uint64_t n = 1);
76
77
virtual
void
PrepareProcessing() {
78
ringbuffer_serial_number_ = 0;
79
80
if
(!connected()) {
81
return
;
82
}
83
84
ringbuffer_->ForcePublish(-1L);
85
ringbuffer_->Claim(-1L);
86
}
87
88
public
:
89
StreamInfo<DATATYPE>
streaminfo_;
// owned by SlotOut, once finalized, the streaminfo (and
90
// datatype) are fixed for the life time of the slot(?)
91
std::unique_ptr<RingBuffer<typename DATATYPE::Data>> ringbuffer_ =
nullptr
;
92
93
protected
:
94
uint64_t ringbuffer_serial_number_;
95
};
96
97
template
<
typename
DATATYPE>
98
class
PortOut :
public
IPortOut {
99
public
:
100
PortOut(IProcessor* parent,
const
PortAddress
& address,
101
const
typename
DATATYPE::Parameters& parameters,
const
PortOutPolicy
& policy)
102
: IPortOut(parent, address, policy), parameters_(parameters) {
103
NewSlot(policy.min_slot_number());
104
}
105
106
SlotType number_of_slots()
const override
{
return
slots_.size(); }
107
std::string datatype()
const override
{
return
DATATYPE::datatype(); }
108
109
StreamInfo<DATATYPE>
& streaminfo(std::size_t index) {
return
slots_[index]->streaminfo(); }
110
111
const
typename
DATATYPE::Data& prototype(std::size_t index)
const
{
112
return
slots_[index]->prototype();
113
}
114
115
virtual
SlotOut<DATATYPE>
* slot(std::size_t index)
override
{
return
slots_[index].get(); }
116
117
SlotOut<DATATYPE>
* dataslot(std::size_t index) {
return
slots_[index].get(); }
118
119
protected
:
120
// called by StreamOutConnector
121
void
Connect(
int
slot,
ISlotIn
* downstream)
override
;
122
int
ReserveSlot(
int
slot)
override
;
123
124
// called by IPortOut
125
void
CreateRingBuffers()
override
;
126
void
UnlockSlots()
override
;
127
128
// called by PortOut<DATATYPE>::Connect
129
virtual
void
NewSlot(
int
n = 1)
override
;
130
131
void
PrepareProcessing()
override
{
132
for
(
auto
& it : slots_) {
133
it->PrepareProcessing();
134
}
135
}
136
137
private
:
138
typename
DATATYPE::Parameters parameters_;
// default parameters
139
std::vector<std::unique_ptr<SlotOut<DATATYPE>>> slots_;
140
};
141
142
template
<
typename
DATATYPE>
143
class
SlotIn :
public
ISlotIn {
144
friend
class
PortIn<DATATYPE>;
145
146
public
:
147
SlotIn(PortIn<DATATYPE>* parent,
const
SlotAddress
& address,
148
typename
DATATYPE::Capabilities capabilities,
bool
cache =
false
)
149
: ISlotIn(parent, address, cache), capabilities_(capabilities) {}
150
156
// const typename DATATYPE::Data *GetDataPrototype() const;
157
166
bool
RetrieveData
(
typename
DATATYPE::Data*& data, int64_t time_out = -1);
175
bool
RetrieveDataN
(uint64_t n, std::vector<typename DATATYPE::Data*>& data,
176
int64_t time_out = -1);
185
bool
RetrieveDataAll
(std::vector<typename DATATYPE::Data*>& data, int64_t time_out = -1);
186
192
bool
FlushData
() {
193
std::vector<typename DATATYPE::Data*> data;
194
if
(!
RetrieveDataAll
(data, 0)) {
195
return
false
;
196
}
197
198
auto
nread = status_read();
199
200
if
(nread == 0) {
201
ReleaseData();
202
}
203
return
true
;
204
}
205
const
IStreamInfo
& streaminfo() {
206
if
(!connected()) {
207
throw
std::runtime_error(
"Input slot is not connected"
);
208
}
209
210
NegotiateUpstream();
211
212
return
upstream_->streaminfo();
213
}
214
215
const
typename
DATATYPE::Data& prototype() {
216
return
streaminfo().template getDataPrototype<typename DATATYPE::Data>();
217
}
218
219
bool
status_alive()
const
{
return
status_.alive; }
220
uint64_t status_read()
const
{
return
status_.read; }
221
uint64_t status_backlog()
const
{
return
status_.backlog; }
222
223
void
Validate()
override
{
224
try
{
225
// the template keyword is necessary here for the compiler
226
// to know how to interpret the code
227
// see https://stackoverflow.com/a/613132
228
auto
prototype =
229
this->streaminfo().template getDataPrototype<typename DATATYPE::Data>();
230
capabilities_.Validate(prototype);
231
}
catch
(
const
std::bad_cast& e) {
232
throw
std::runtime_error(
"Incompatible data types ("
+ this->streaminfo().datatype() +
233
" -> "
+ DATATYPE::datatype() +
")."
);
234
}
catch
(
const
std::exception& e) {
235
throw
;
236
}
237
}
238
239
protected
:
240
void
Unlock();
241
void
check_high_water_level();
242
243
RingBufferStatus status_;
244
245
const
double
HIGH_WATER_LEVEL = 0.85;
246
unsigned
int
n_messages_;
247
const
unsigned
int
MAX_N_MESSAGES = 20;
248
249
typename
DATATYPE::Capabilities capabilities_;
250
251
public
:
252
typename
DATATYPE::Data* cache_;
253
};
254
255
template
<
typename
DATATYPE>
256
class
PortIn :
public
IPortIn {
257
public
:
258
PortIn(IProcessor* parent,
const
PortAddress
& address,
259
const
typename
DATATYPE::Capabilities& capabilities,
const
PortInPolicy
& policy)
260
: IPortIn(parent, address, policy), capabilities_(capabilities) {
261
NewSlot(policy.min_slot_number());
262
}
263
264
SlotType number_of_slots()
const override
{
return
slots_.size(); }
265
266
virtual
SlotIn<DATATYPE>
* slot(std::size_t index)
override
{
return
slots_[index].get(); }
267
SlotIn<DATATYPE>
* dataslot(std::size_t index) {
return
slots_[index].get(); }
268
269
std::string datatype()
const override
{
return
DATATYPE::datatype(); }
270
271
const
IStreamInfo
& streaminfo(std::size_t index) {
return
slots_[index]->streaminfo(); }
272
273
const
typename
DATATYPE::Data& prototype(std::size_t index) {
274
return
slots_[index]->prototype();
275
}
276
277
void
PrepareProcessing()
override
{
278
for
(
auto
& it : slots_) {
279
it->PrepareProcessing();
280
}
281
}
282
283
protected
:
284
// called by StreamInConnector
285
virtual
void
Connect(
int
slot,
ISlotOut
* upstream)
override
;
286
virtual
int
ReserveSlot(
int
slot)
override
;
287
288
void
UnlockSlots()
override
;
289
void
NewSlot(
int
n = 1);
290
291
private
:
292
typename
DATATYPE::Capabilities capabilities_;
293
std::vector<std::unique_ptr<SlotIn<DATATYPE>>> slots_;
294
};
295
296
#include "streamports.ipp"
ISlotIn
Definition
istreamports.hpp:126
ISlotOut
Definition
istreamports.hpp:40
IStreamInfo
Definition
streaminfo.hpp:31
PortAddress
Definition
connections.hpp:24
PortInPolicy
Definition
portpolicy.hpp:43
PortIn
Definition
streamports.hpp:256
PortOutPolicy
Definition
portpolicy.hpp:54
PortOut
Definition
streamports.hpp:98
PortPolicy
Definition
portpolicy.hpp:28
SlotAddress
Definition
connections.hpp:54
SlotIn
Definition
streamports.hpp:143
SlotIn::FlushData
bool FlushData()
Flush all data already in the ring buffer without retrieve them - method used from the processor impl...
Definition
streamports.hpp:192
SlotIn::RetrieveData
bool RetrieveData(typename DATATYPE::Data *&data, int64_t time_out=-1)
get a prototype example of a data packet - method used from the processor implementation
SlotIn::RetrieveDataN
bool RetrieveDataN(uint64_t n, std::vector< typename DATATYPE::Data * > &data, int64_t time_out=-1)
Retrieve N data packets in the ring buffer - method used from the processor implementation.
SlotIn::RetrieveDataAll
bool RetrieveDataAll(std::vector< typename DATATYPE::Data * > &data, int64_t time_out=-1)
Retrieve all data packets in the ring buffer - method used from the processor implementation.
SlotOut
Definition
streamports.hpp:47
StreamInfo
Definition
streaminfo.hpp:73
RingBufferStatus
Definition
streamports.hpp:30
falcon
streamports.hpp
Generated by
1.18.0