Lumiera  0.pre.03
»edit your freedom«
diagnostic-output-slot.hpp
Go to the documentation of this file.
1 /*
2  DIAGNOSTIC-OUTPUT-SLOT.hpp - helper for testing against the OutputSlot interface
3 
4  Copyright (C)
5  2011, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
21 #ifndef STEAM_PLAY_DIAGNOSTIC_OUTPUT_SLOT_H
22 #define STEAM_PLAY_DIAGNOSTIC_OUTPUT_SLOT_H
23 
24 
25 #include "lib/error.hpp"
26 #include "lib/nocopy.hpp"
27 #include "include/logging.h"
33 #include "lib/time/timevalue.hpp"
34 #include "lib/scoped-ptrvect.hpp"
35 #include "lib/iter-source.hpp"
36 #include "lib/symbol.hpp"
37 #include "lib/util.hpp"
38 #include "common/advice.hpp"
40 //#include "lib/sync.hpp"
41 
42 //#include <string>
43 //#include <vector>
44 #include <unordered_set>
45 #include <memory>
46 
47 
48 namespace steam {
49 namespace play {
50 
51 //using std::string;
52  using lib::Symbol;
53  using util::unConst;
54  using util::contains;
61  namespace diagn = steam::engine::diagn;
62 
63 //using std::vector;
64  using std::shared_ptr;
65 
66  namespace { // diagnostics & internals....
67 
68  inline PGrid
69  getTestTimeGrid()
70  {
71  Symbol gridID("DiagnosticOutputSlot-buffer-grid");
72  lumiera::advice::Request<PGrid> query4grid(gridID) ;
73  PGrid testGrid25 = query4grid.getAdvice();
74 
75  if (!testGrid25)
76  testGrid25 = TimeGrid::build (gridID, FrameRate::PAL);
77 
78  ENSURE (testGrid25);
79  return testGrid25;
80  }
81  }
82 
83 
90  : public OutputSlot::Connection
92  {
93 
94  typedef std::unordered_set<FrameID> FrameTrackingInfo;
95 
96 
97  TrackingHeapBlockProvider buffProvider_;
98  BuffDescr bufferType_;
99 
100  FrameTrackingInfo frameTrackingIndex_;
101  PGrid frameGrid_;
102 
103  bool closed_;
104 
105 
106  BuffHandle
107  trackFrame (FrameID frameNr, BuffHandle const& newBuffer)
108  {
109  TRACE (test, "Con=%p : track buffer %zu for frame-#%lu"
110  , this, newBuffer.entryID(), frameNr);
111  REQUIRE (!contains (frameTrackingIndex_,frameNr),
112  "attempt to lock already used frame %lu", frameNr);
113 
114  frameTrackingIndex_.insert (frameNr);
115  return newBuffer;
116  }
117 
118  TimeValue
119  deadlineFor (FrameID frameNr)
120  {
121  // a real world implementation
122  // would offset by a latency here
123  return frameGrid_->timeOf (frameNr);
124  }
125 
126 
127 
128 
129  /* === Connection API === */
130 
131  BuffHandle
132  claimBufferFor(FrameID frameNr)
133  {
134  TRACE (test, "Con=%p : lock buffer for frame-#%lu", this, frameNr);
135  REQUIRE (!closed_);
136 
137  return trackFrame (frameNr,
138  buffProvider_.lockBuffer (bufferType_));
139  }
140 
141 
142  bool
143  isTimely (FrameID frameNr, TimeValue currentTime)
144  {
145  TRACE (test, "Con=%p : timely? frame-#%lu"
146  , this, frameNr);
147 
148  if (Time::ANYTIME == currentTime)
149  return true;
150  else
151  return currentTime < deadlineFor (frameNr);
152  }
153 
154  void
155  transfer (BuffHandle const& filledBuffer)
156  {
157  TRACE (test, "Con=%p : transfer buffer %zu"
158  , this, filledBuffer.entryID());
159  REQUIRE (!closed_);
160 
161  pushout (filledBuffer);
162  }
163 
164  void
165  pushout (BuffHandle const& data4output)
166  {
167  REQUIRE (!closed_);
168  buffProvider_.emitBuffer (data4output);
169  buffProvider_.releaseBuffer(data4output);
170  }
171 
172  void
173  discard (BuffHandle const& superseededData)
174  {
175  REQUIRE (!closed_);
176  buffProvider_.releaseBuffer (superseededData);
177  }
178 
179  void
180  shutDown ()
181  {
182  closed_ = true;
183  }
184 
185  public:
187  : buffProvider_()
188  , bufferType_(buffProvider_.getDescriptor<TestFrame>())
189  , frameTrackingIndex_()
190  , frameGrid_(getTestTimeGrid())
191  , closed_(false)
192  {
193  INFO (engine_dbg, "building in-memory diagnostic output sequence (at %p)", this);
194  }
195 
196  virtual
198  {
199  INFO (engine_dbg, "releasing diagnostic output sequence (at %p)", this);
200  }
201 
202 
203  /* === Diagnostic API === */
204 
205  TestFrame const *
206  accessEmittedFrame (uint frameNr) const
207  {
208  if (frameNr < buffProvider_.emittedCnt())
209  return & accessFrame(frameNr);
210  else
211  return 0;
212  }
213 
214  diagn::Block const *
215  accessEmittedBuffer (uint bufferNr) const
216  {
217  if (bufferNr < buffProvider_.emittedCnt())
218  return & accessBlock(bufferNr);
219  else
220  return 0;
221  }
222 
223  bool
224  wasAllocated (uint frameNr) const
225  {
226  TRACE (test, "query wasAllocated. Con=%p", this);
227 
228  return contains (frameTrackingIndex_, frameNr);
229  }
230 
231  private:
232  TestFrame const&
233  accessFrame (uint frameNr) const
234  {
235  return unConst(this)->buffProvider_.accessAs<TestFrame> (frameNr);
236  }
237 
238  diagn::Block const&
239  accessBlock (uint bufferNr) const
240  {
241  return unConst(this)->buffProvider_.access_emitted (bufferNr);
242  }
243  };
244 
245 
246 
247 
248 
249 
250 
251 
252 
253  /****************************************************************/
267  : public OutputSlotImplBase
268  {
269 
270  static const uint MAX_CHANNELS = 5;
271 
275  uint
277  {
278  return MAX_CHANNELS;
279  }
280 
281 
288  : public ConnectionManager<TrackingInMemoryBlockSequence>
289  {
290  typedef ConnectionManager<TrackingInMemoryBlockSequence> _Base;
291 
292  void
293  buildConnection(ConnectionStorage storage)
294  {
295  storage.create<TrackingInMemoryBlockSequence>();
296  }
297 
298  public:
299  SimulatedOutputSequences (uint numChannels)
300  : _Base(numChannels)
301  {
302  init();
303  }
304  };
305 
306 
307 
311  {
312  return new SimulatedOutputSequences(
313  getOutputChannelCount());
314  }
315 
319 
324  accessSequence (uint channel)
325  {
326  REQUIRE (!isFree(), "diagnostic OutputSlot not (yet) connected");
327  REQUIRE (channel <= getOutputChannelCount());
328  return static_cast<TrackingInMemoryBlockSequence&> (state_->access (channel));
329  }
330 
331 
332  public:
336  static OutputSlot&
338  {
339  static lib::ScopedPtrVect<OutputSlot> diagnosticSlots;
340  return diagnosticSlots.manage(new DiagnosticOutputSlot);
341  }
342 
343  static DiagnosticOutputSlot&
344  access (OutputSlot& to_investigate)
345  {
346  return dynamic_cast<DiagnosticOutputSlot&> (to_investigate);
347  }
348 
349 
350 
351  /* === diagnostics API === */
352 
359  : public lib::IterSource<const TestFrame>
361  {
362  TrackingInMemoryBlockSequence const& outSeq_;
363  uint currentFrame_;
364 
365 
366  virtual Pos
367  firstResult () override
368  {
369  REQUIRE (0 == currentFrame_);
370  return outSeq_.accessEmittedFrame (currentFrame_);
371  }
372 
373  virtual void
374  nextResult (Pos& pos) override
375  {
376  ++currentFrame_;
377  pos = outSeq_.accessEmittedFrame(currentFrame_);
378  }
379 
380  public:
382  : outSeq_(bs)
383  , currentFrame_(0)
384  { }
385  };
386 
387  typedef OutputFramesLog::iterator OutFrames;
388 
389 
390  OutFrames
391  getChannel (uint channel)
392  {
393  REQUIRE (channel < MAX_CHANNELS);
394  return OutputFramesLog::build(
395  new OutputFramesLog (
396  accessSequence(channel)));
397  }
398 
399 
400  bool
401  frame_was_allocated (uint channel, FrameID nominalFrame)
402  {
403  return accessSequence(channel)
404  .wasAllocated(nominalFrame);
405  }
406 
407 
408  bool
409  output_was_emitted (uint channel, FrameID outputFrame)
410  {
411  diagn::Block const *block = accessSequence(channel)
412  .accessEmittedBuffer(outputFrame);
413  return block
414  && block->was_used();
415  }
416 
417 
418  bool
419  output_was_closed (uint channel, FrameID outputFrame)
420  {
421  diagn::Block const *block = accessSequence(channel)
422  .accessEmittedBuffer(outputFrame);
423  return block
424  && block->was_closed();
425  }
426  };
427 
428 
429 
430 }} // namespace steam::play
431 #endif
static const Time ANYTIME
border condition marker value. ANYTIME <= any time value
Definition: timevalue.hpp:313
Helper for implementing a diagnostic BufferProvider: A block of heap allocated storage, with the capability to store some additional tracking information.
An (abstract) capability to send media data to an external output.
Interface: a grid and scale definition for time quantisation.
Definition: time-grid.hpp:77
Access point for the advised entity (client).
Definition: advice.hpp:428
TrackingInMemoryBlockSequence const & accessSequence(uint channel)
Mock data frame for simulated rendering.
Definition: testframe.hpp:68
void releaseBuffer(BuffHandle const &)
BufferProvider API: declare done and detach.
Definition: run.hpp:40
Framerate specified as frames per second.
Definition: timevalue.hpp:655
Any copy and copy construction prohibited.
Definition: nocopy.hpp:37
static PGrid build(FrameRate frames_per_second)
Definition: time-grid.cpp:158
An opaque descriptor to identify the type and further properties of a data buffer.
Definition: buffhandle.hpp:77
This header is for including and configuring NoBug.
Steam-Layer implementation namespace root.
Managing lifecycle for a collection of objects.
Simple vector based collection of pointers, managing lifecycle of the pointed-to objects.
ConnectionState * buildState()
hook into the OutputSlot frontend
Token or Atom with distinct identity.
Definition: symbol.hpp:117
Iteration source interface to abstract a data source, which then can be accessed through IterAdapter ...
Definition: iter-source.hpp:79
Helper for unit tests: Mock output sink.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Expecting Advice and giving Advice: a cross-cutting collaboration of loosely coupled participants...
Base for OutputSlot standard implementation.
BuffDescr getDescriptor(ARGS ...args)
define a "buffer type" for automatically creating an instance of the template type embedded into the ...
Extension point for Implementation.
Marker types to indicate a literal string and a Symbol.
Dummy implementation of the BufferProvider interface to support writing unit tests.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
BuffHandle lockBuffer(BuffDescr const &)
BufferProvider API: retrieve a single buffer for exclusive use.
Interface for concrete output implementations to talk to the OutputSlot frontend. ...
Special diagnostic connection state implementation, establishing diagnostic output connections for ea...
A front-end to support the buffer management within the render nodes.
simple BufferProvider implementation with additional allocation tracking.
Lumiera error handling (C++ interface).
Interface: Generic output sink.
Handle for a buffer for processing data, abstracting away the actual implementation.
Definition: buffhandle.hpp:111
To establish a reference scale for quantised time values.
Customised refcounting smart pointer template, built upon std::shared_ptr, but forwarding type relati...
Definition: trait.hpp:71
void emitBuffer(BuffHandle const &)
BufferProvider API: state transition to emitted state.
static OutputSlot & build()
build a new Diagnostic Output Slot instance, discard the existing one.
a family of time value like entities and their relationships.
Unit test helper to generate fake test data frames.
Extension module to build an opaque data source, accessible as Lumiera Forward Iterator.
basic constant internal time value.
Definition: timevalue.hpp:133
T & manage(T *obj)
take ownership of the given object, adding it at the end of the collection
virtual Pos firstResult() override
iteration start: prepare the first element.
Diagnostic output connection for a single channel, allowing to track generated frames and verify the ...
diagnostic facility to verify test data frames written to this Test/Dummy "output".
virtual void nextResult(Pos &pos) override
iteration step: switch on to the next element.
static const FrameRate PAL
predefined constant for PAL framerate
Definition: timevalue.hpp:671
bool contains(SEQ const &cont, typename SEQ::const_reference val)
shortcut for brute-force containment test in any sequential container
Definition: util.hpp:255