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) Lumiera.org
5  2011, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
30 #ifndef STEAM_PLAY_DIAGNOSTIC_OUTPUT_SLOT_H
31 #define STEAM_PLAY_DIAGNOSTIC_OUTPUT_SLOT_H
32 
33 
34 #include "lib/error.hpp"
35 #include "lib/nocopy.hpp"
36 #include "include/logging.h"
42 #include "lib/time/timevalue.hpp"
43 #include "lib/scoped-ptrvect.hpp"
44 #include "lib/iter-source.hpp"
45 #include "lib/symbol.hpp"
46 #include "lib/util.hpp"
47 #include "common/advice.hpp"
49 //#include "lib/sync.hpp"
50 
51 //#include <string>
52 //#include <vector>
53 #include <unordered_set>
54 #include <memory>
55 
56 
57 namespace steam {
58 namespace play {
59 
60 //using std::string;
61  using lib::Symbol;
62  using util::unConst;
63  using util::contains;
70  namespace diagn = steam::engine::diagn;
71 
72 //using std::vector;
73  using std::shared_ptr;
74 
75  namespace { // diagnostics & internals....
76 
77  inline PGrid
78  getTestTimeGrid()
79  {
80  Symbol gridID("DiagnosticOutputSlot-buffer-grid");
81  lumiera::advice::Request<PGrid> query4grid(gridID) ;
82  PGrid testGrid25 = query4grid.getAdvice();
83 
84  if (!testGrid25)
85  testGrid25 = TimeGrid::build (gridID, FrameRate::PAL);
86 
87  ENSURE (testGrid25);
88  return testGrid25;
89  }
90  }
91 
92 
99  : public OutputSlot::Connection
101  {
102 
103  typedef std::unordered_set<FrameID> FrameTrackingInfo;
104 
105 
106  TrackingHeapBlockProvider buffProvider_;
107  BufferDescriptor bufferType_;
108 
109  FrameTrackingInfo frameTrackingIndex_;
110  PGrid frameGrid_;
111 
112  bool closed_;
113 
114 
115  BuffHandle
116  trackFrame (FrameID frameNr, BuffHandle const& newBuffer)
117  {
118  TRACE (test, "Con=%p : track buffer %zu for frame-#%lu"
119  , this, newBuffer.entryID(), frameNr);
120  REQUIRE (!contains (frameTrackingIndex_,frameNr),
121  "attempt to lock already used frame %lu", frameNr);
122 
123  frameTrackingIndex_.insert (frameNr);
124  return newBuffer;
125  }
126 
127  TimeValue
128  deadlineFor (FrameID frameNr)
129  {
130  // a real world implementation
131  // would offset by a latency here
132  return frameGrid_->timeOf (frameNr);
133  }
134 
135 
136 
137 
138  /* === Connection API === */
139 
140  BuffHandle
141  claimBufferFor(FrameID frameNr)
142  {
143  TRACE (test, "Con=%p : lock buffer for frame-#%lu", this, frameNr);
144  REQUIRE (!closed_);
145 
146  return trackFrame (frameNr,
147  buffProvider_.lockBuffer (bufferType_));
148  }
149 
150 
151  bool
152  isTimely (FrameID frameNr, TimeValue currentTime)
153  {
154  TRACE (test, "Con=%p : timely? frame-#%lu"
155  , this, frameNr);
156 
157  if (Time::ANYTIME == currentTime)
158  return true;
159  else
160  return currentTime < deadlineFor (frameNr);
161  }
162 
163  void
164  transfer (BuffHandle const& filledBuffer)
165  {
166  TRACE (test, "Con=%p : transfer buffer %zu"
167  , this, filledBuffer.entryID());
168  REQUIRE (!closed_);
169 
170  pushout (filledBuffer);
171  }
172 
173  void
174  pushout (BuffHandle const& data4output)
175  {
176  REQUIRE (!closed_);
177  buffProvider_.emitBuffer (data4output);
178  buffProvider_.releaseBuffer(data4output);
179  }
180 
181  void
182  discard (BuffHandle const& superseededData)
183  {
184  REQUIRE (!closed_);
185  buffProvider_.releaseBuffer (superseededData);
186  }
187 
188  void
189  shutDown ()
190  {
191  closed_ = true;
192  }
193 
194  public:
196  : buffProvider_()
197  , bufferType_(buffProvider_.getDescriptor<TestFrame>())
198  , frameTrackingIndex_()
199  , frameGrid_(getTestTimeGrid())
200  , closed_(false)
201  {
202  INFO (engine_dbg, "building in-memory diagnostic output sequence (at %p)", this);
203  }
204 
205  virtual
207  {
208  INFO (engine_dbg, "releasing diagnostic output sequence (at %p)", this);
209  }
210 
211 
212  /* === Diagnostic API === */
213 
214  TestFrame const *
215  accessEmittedFrame (uint frameNr) const
216  {
217  if (frameNr < buffProvider_.emittedCnt())
218  return & accessFrame(frameNr);
219  else
220  return 0;
221  }
222 
223  diagn::Block const *
224  accessEmittedBuffer (uint bufferNr) const
225  {
226  if (bufferNr < buffProvider_.emittedCnt())
227  return & accessBlock(bufferNr);
228  else
229  return 0;
230  }
231 
232  bool
233  wasAllocated (uint frameNr) const
234  {
235  TRACE (test, "query wasAllocated. Con=%p", this);
236 
237  return contains (frameTrackingIndex_, frameNr);
238  }
239 
240  private:
241  TestFrame const&
242  accessFrame (uint frameNr) const
243  {
244  return unConst(this)->buffProvider_.accessAs<TestFrame> (frameNr);
245  }
246 
247  diagn::Block const&
248  accessBlock (uint bufferNr) const
249  {
250  return unConst(this)->buffProvider_.access_emitted (bufferNr);
251  }
252  };
253 
254 
255 
256 
257 
258 
259 
260 
261 
262  /****************************************************************/
276  : public OutputSlotImplBase
277  {
278 
279  static const uint MAX_CHANNELS = 5;
280 
284  uint
286  {
287  return MAX_CHANNELS;
288  }
289 
290 
297  : public ConnectionManager<TrackingInMemoryBlockSequence>
298  {
299  typedef ConnectionManager<TrackingInMemoryBlockSequence> _Base;
300 
301  void
302  buildConnection(ConnectionStorage storage)
303  {
304  storage.create<TrackingInMemoryBlockSequence>();
305  }
306 
307  public:
308  SimulatedOutputSequences (uint numChannels)
309  : _Base(numChannels)
310  {
311  init();
312  }
313  };
314 
315 
316 
320  {
321  return new SimulatedOutputSequences(
322  getOutputChannelCount());
323  }
324 
328 
333  accessSequence (uint channel)
334  {
335  REQUIRE (!isFree(), "diagnostic OutputSlot not (yet) connected");
336  REQUIRE (channel <= getOutputChannelCount());
337  return static_cast<TrackingInMemoryBlockSequence&> (state_->access (channel));
338  }
339 
340 
341  public:
345  static OutputSlot&
347  {
348  static lib::ScopedPtrVect<OutputSlot> diagnosticSlots;
349  return diagnosticSlots.manage(new DiagnosticOutputSlot);
350  }
351 
352  static DiagnosticOutputSlot&
353  access (OutputSlot& to_investigate)
354  {
355  return dynamic_cast<DiagnosticOutputSlot&> (to_investigate);
356  }
357 
358 
359 
360  /* === diagnostics API === */
361 
368  : public lib::IterSource<const TestFrame>
370  {
371  TrackingInMemoryBlockSequence const& outSeq_;
372  uint currentFrame_;
373 
374 
375  virtual Pos
376  firstResult () override
377  {
378  REQUIRE (0 == currentFrame_);
379  return outSeq_.accessEmittedFrame (currentFrame_);
380  }
381 
382  virtual void
383  nextResult (Pos& pos) override
384  {
385  ++currentFrame_;
386  pos = outSeq_.accessEmittedFrame(currentFrame_);
387  }
388 
389  public:
391  : outSeq_(bs)
392  , currentFrame_(0)
393  { }
394  };
395 
396  typedef OutputFramesLog::iterator OutFrames;
397 
398 
399  OutFrames
400  getChannel (uint channel)
401  {
402  REQUIRE (channel < MAX_CHANNELS);
403  return OutputFramesLog::build(
404  new OutputFramesLog (
405  accessSequence(channel)));
406  }
407 
408 
409  bool
410  frame_was_allocated (uint channel, FrameID nominalFrame)
411  {
412  return accessSequence(channel)
413  .wasAllocated(nominalFrame);
414  }
415 
416 
417  bool
418  output_was_emitted (uint channel, FrameID outputFrame)
419  {
420  diagn::Block const *block = accessSequence(channel)
421  .accessEmittedBuffer(outputFrame);
422  return block
423  && block->was_used();
424  }
425 
426 
427  bool
428  output_was_closed (uint channel, FrameID outputFrame)
429  {
430  diagn::Block const *block = accessSequence(channel)
431  .accessEmittedBuffer(outputFrame);
432  return block
433  && block->was_closed();
434  }
435  };
436 
437 
438 
439 }} // namespace steam::play
440 #endif
static const Time ANYTIME
border condition marker value. ANYTIME <= any time value
Definition: timevalue.hpp:322
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:86
Access point for the advised entity (client).
Definition: advice.hpp:437
TrackingInMemoryBlockSequence const & accessSequence(uint channel)
Mock data frame for simulated rendering.
Definition: testframe.hpp:60
void releaseBuffer(BuffHandle const &)
BufferProvider API: declare done and detach.
Definition: run.hpp:49
Framerate specified as frames per second.
Definition: timevalue.hpp:664
Any copy and copy construction prohibited.
Definition: nocopy.hpp:46
static PGrid build(FrameRate frames_per_second)
Definition: time-grid.cpp:167
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:126
Iteration source interface to abstract a data source, which then can be accessed through IterAdapter ...
Definition: iter-source.hpp:88
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.
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...
An opaque descriptor to identify the type and further properties of a data buffer.
Definition: buffhandle.hpp:85
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.
BuffHandle lockBuffer(BufferDescriptor const &)
BufferProvider API: retrieve a single buffer for exclusive use.
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:115
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:80
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:142
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:680
bool contains(SEQ const &cont, typename SEQ::const_reference val)
shortcut for brute-force containment test in any sequential container
Definition: util.hpp:255
BufferDescriptor getDescriptor()
define a "buffer type" for automatically creating an instance of the template type embedded into the ...