MatLogger2  1.0.0
Library for logging of numeric data to HDF5 MAT-files, which is RT-safe and multithreaded.
var_buffer.h
Go to the documentation of this file.
1 #ifndef __XBOT_MATLOGGER2_BUFFER_BLOCK__
2 #define __XBOT_MATLOGGER2_BUFFER_BLOCK__
3 
4 #include <string>
5 #include <memory>
6 
7 #include <eigen3/Eigen/Dense>
8 
9 namespace XBot
10 {
11 
33  {
34 
35  public:
36 
40  enum class Mode
41  {
42  // producer-consumer mode (possibly dual thread):
43  // the user (or the provided MatAppender)
44  // is responsible for keeping the buffer free
46 
47  // circular buffer mode (single thread)
49  };
50 
51  struct BufferInfo
52  {
53  // name of the variable that the new data refers to
54  const char * variable_name;
55 
56  // bytes available to be flushed to disk
58 
59  // free space available in buffer (0..1, 0 indicates full buffer)
61  };
62 
63  typedef std::function<void(BufferInfo)> CallbackType;
64 
73  VariableBuffer(std::string name,
74  int dim_rows, int dim_cols,
75  int block_size);
76 
81  void set_on_block_available(CallbackType callback);
82 
91 
92  const std::string& get_name() const;
93 
94  std::pair<int, int> get_dimension() const;
95 
107  template <typename Derived>
108  bool add_elem(const Eigen::MatrixBase<Derived>& data);
109 
122  bool read_block(Eigen::MatrixXd& data,
123  int& valid_elements);
124 
131  bool flush_to_queue();
132 
133  static int NumBlocks();
134 
135  ~VariableBuffer();
136 
137  private:
138 
144  class BufferBlock
145  {
146 
147  public:
148 
149  typedef std::shared_ptr<BufferBlock> Ptr;
150 
151  BufferBlock();
152 
157  BufferBlock(int dim, int block_size);
158 
159 
167  template <typename Derived>
168  bool add(const Eigen::MatrixBase<Derived>& data);
169 
170 
174  void reset();
175 
181  const Eigen::MatrixXd& get_data() const;
182 
183 
188  int get_valid_elements() const;
189 
190  int get_size() const;
191  int get_size_bytes() const;
192 
193 
194  private:
195 
196  // current write index (also equals the number of valid elements)
197  int _write_idx;
198 
199  // memory for get_size() elements, stored column-wise
200  Eigen::MatrixXd _buf;
201 
202  };
203 
204  // mode
205  Mode _buffer_mode;
206 
207  // variable name
208  std::string _name;
209 
210  // variable dimensions
211  int _rows;
212  int _cols;
213 
214  // current block
215  BufferBlock::Ptr _current_block;
216 
217  // fifo spsc queue of blocks
218  class QueueImpl;
219  std::unique_ptr<QueueImpl> _queue;
220 
221  // function to be called when a block is pushed into the queue
222  CallbackType _on_block_available;
223 
224  };
225 
226 
227 
228 }
229 
230 
231 
232 template <typename Derived>
233 inline bool XBot::VariableBuffer::BufferBlock::add(const Eigen::MatrixBase<Derived>& data)
234 {
235  // check if the block is full, and return false
236  if(_write_idx == get_size())
237  {
238  return false;
239  }
240 
241  // pointer to the _write_idx-th element (column of _buf)
242  double * col_ptr = _buf.data() + _write_idx*_buf.rows();
243 
244  // Eigen-view on the column to be written
245  Eigen::Map<Eigen::MatrixXd> elem_map(col_ptr,
246  data.rows(), data.cols());
247 
248  // cast data do double and write it to the current element
249  elem_map.noalias() = data.template cast<double>();
250 
251  // increase _write_idx
252  _write_idx++;
253 
254  // if the block is not full, return true
255  return true;
256 }
257 
258 
259 template <typename Derived>
260 inline bool XBot::VariableBuffer::add_elem(const Eigen::MatrixBase<Derived>& data)
261 {
262  // check data size correctness
263  if( data.size() != _rows*_cols )
264  {
265  fprintf(stderr, "Unable to add element to variable '%s': \
266 size does not match (%d vs %d)\n",
267  _name.c_str(), (int)data.size(), _rows*_cols);
268 
269  return false;
270  }
271 
272  // if current block is full, we push it into the queue, and try again
273  if(!_current_block->add(data))
274  {
275 
276  // write current block to queue
277  flush_to_queue();
278 
279  // reset current block
280  _current_block->reset();
281 
282  return add_elem(data);
283  }
284 
285  return true;
286 }
287 
288 
289 
290 #endif
std::pair< int, int > get_dimension() const
Definition: var_buffer.cpp:150
bool flush_to_queue()
Writes current block to the queue.
Definition: var_buffer.cpp:196
void set_buffer_mode(VariableBuffer::Mode mode)
Set whether this buffer should be treated as a (possibly dual threaded) producer-consumer queue...
Definition: var_buffer.cpp:266
Mode
Enum for specifying the type of buffer.
Definition: var_buffer.h:40
bool add_elem(const Eigen::MatrixBase< Derived > &data)
Add an element to the buffer.
Definition: var_buffer.h:260
bool read_block(Eigen::MatrixXd &data, int &valid_elements)
Reads a whole block from the queue, if one is available.
Definition: var_buffer.cpp:165
VariableBuffer(std::string name, int dim_rows, int dim_cols, int block_size)
Constructor.
Definition: var_buffer.cpp:136
static int NumBlocks()
Definition: var_buffer.cpp:261
The VariableBuffer class implements a memory buffer for a single logged variable. ...
Definition: var_buffer.h:32
std::function< void(BufferInfo)> CallbackType
Definition: var_buffer.h:63
void set_on_block_available(CallbackType callback)
Sets a callback that is used to notify that a new block has been pushed into the queue.
Definition: var_buffer.cpp:155
const std::string & get_name() const
Definition: matlogger2.cpp:42
The QueueImpl class implements the buffering strategy for a single logged variable.
Definition: var_buffer.cpp:52