Test-driven brainstorming: diagnostic adaptor for the engine

This commit is contained in:
Fischlurch 2011-08-16 03:02:55 +02:00
parent 3125d1c573
commit 737765260d
8 changed files with 353 additions and 30 deletions

View file

@ -0,0 +1,105 @@
/*
ENGINE-DIAGNOSTICS.hpp - diagnostic facility to investigate engine operation
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file engine-diagnostics.hpp
** An facility to check and monitor engine operations.
** Once created, an EngineDiagnostics object connects to the EngineService
** interface to activate additional tracing facilities within the engine,
** allowing to watch and verify the creation of individual jobs and further
** engine state parameters.
**
** @see EngineInterface
** @see engine-interface-test.cpp
** @see calc-stream-test.cpp
*/
#ifndef PROC_ENGINE_ENGINE_DIAGNOSTICS_H
#define PROC_ENGINE_ENGINE_DIAGNOSTICS_H
#include "lib/error.hpp"
#include "proc/engine/engine-service.hpp"
//#include "include/dummy-player-facade.h"
//#include "include/display-facade.h"
//#include "proc/engine/calc-stream.hpp"
//#include "proc/mobject/model-port.hpp"
//#include "proc/play/timings.hpp"
//#include "proc/play/output-slot.hpp"
//#include "common/instancehandle.hpp"
//#include "lib/singleton-ref.hpp"
//#include "lib/polymorphic-value.hpp"
//#include "lib/singleton.hpp"
//
#include <boost/noncopyable.hpp>
//#include <boost/scoped_ptr.hpp>
//#include <string>
namespace proc {
namespace engine{
// using std::string;
// using lumiera::Subsys;
// using lumiera::Display;
// using lumiera::DummyPlayer;
/******************************************************
* Render engine diagnostic facility. Creating an instance
* will activate additional tracing facilities within the
* render engine; results may be investigated through
* EngineDiagnostics public functions. The object acts
* like a smart handle, i.e. the tracing facilities will
* be disabled and disconnected when going out of scope.
*/
class EngineDiagnostics
: boost::noncopyable
{
EngineService& engine_;
public:
EngineDiagnostics (EngineService& e)
: engine_(e)
{
UNIMPLEMENTED ("attach tracing connector");
engine_.activateTracing();
}
~EngineDiagnostics()
{
TODO ("detach tracing connector");
engine_.disableTracing();
}
};
} // namespace engine
} // namespace proc
#endif

View file

@ -38,20 +38,24 @@ namespace engine{
// using std::auto_ptr;
// using boost::scoped_ptr;
// using std::tr1::bind;
namespace { // hidden local details of the service implementation....
} // (End) hidden service impl details
/** storage for the EngineService interface object */
lib::Singleton<EngineService> EngineService::instance;
/** */
EngineService::EngineService()
{ }
/** */
CalcStream

View file

@ -22,12 +22,24 @@
/** @file engine-service.hpp
** Access point for the (core) calculation service of the render engine.
** This public service is provided by the Proc-Layer, but actually implemented
** using backend services (especially the scheduler). The central concept provided
** through this facade interface is that of a <i>calculation stream</i>. On the
** implementation side, these get translated into a series of jobs invoking
** render nodes, to be invoked through the scheduler in the backend layer.
** This Proc-Layer internal service is provided for use by the Player subsystem.
** The actual implementation is forwarded to backend services (especially the scheduler).
** The EngineService singleton has no state beyond the jobs currently managed by the
** scheduler; when the latter isn't available, any invocation will throw.
**
** The central concept provided through this facade interface is the <i>calculation stream</i>.
** This represents a series of calculations, expected to happen in a timely fashion and in order
** to deliver a frame data stream onto an opened output connection. On the implementation side,
** a calculation stream will be translated into a series of jobs invoking render nodes,
** to be executed through the scheduler in the backend layer.
**
** While the individual CalcStram is simple, linear and unmodifiable, any CalcStream may be
** \em superseded by a new definition. In this case, the engine will care for a seamless
** switch and continuation; under the hood, there is a mechanism to discard resources
** tied to the original CalcStream, once the switch to the new definition is complete.
**
** @see EngineInterface_test
** @see CalcStream_test
** @see proc::play::PlayerService
*/
@ -46,6 +58,7 @@
//#include "common/instancehandle.hpp"
//#include "lib/singleton-ref.hpp"
#include "lib/polymorphic-value.hpp"
#include "lib/singleton.hpp"
//
#include <boost/noncopyable.hpp>
//#include <boost/scoped_ptr.hpp>
@ -82,18 +95,6 @@ namespace engine{
: boost::noncopyable
{
// string error_;
// Subsys::SigTerm notifyTermination_;
/* === Interface Lifecycle === */
// typedef lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_DummyPlayer, 0)
// , DummyPlayer
// > ServiceInstanceHandle;
// lib::SingletonRef<DummyPlayerService> implInstance_;
// ServiceInstanceHandle serviceInstance_;
/* The following typedefs allow to hand out predefined
* Quality-of-Service strategy definitions as value objects,
@ -117,8 +118,8 @@ namespace engine{
};
// typedef lib::polyvalue::CloneValueSupport<Quality> _ClonableQoS_Strategy;
typedef lib::PolymorphicValue<Quality, QoS_IMPL_SIZE> QoS_Definition;
typedef lib::polyvalue::CloneValueSupport<Quality> _Clonable_QoS_Strategy;
typedef lib::PolymorphicValue<Quality, QoS_IMPL_SIZE, _Clonable_QoS_Strategy> QoS_Definition;
static QoS_Definition QoS_DEFAULT;
static QoS_Definition QoS_BACKGROUND;
@ -127,10 +128,15 @@ namespace engine{
static QoS_Definition QoS_COMPROMISE;
/** access point to the Engine Interface.
* @internal this is an facade interface for internal use
* by the player. Client code should use the Player.
*/
static lib::Singleton<EngineService> instance;
EngineService(); /////TODO (Subsys::SigTerm terminationHandle);
~EngineService() { } /////TODO notifyTermination_(&error_); }
EngineService();
~EngineService() { }
CalcStream
calculate(ModelPort mPort,
@ -143,6 +149,12 @@ namespace engine{
Timings nominalTimings,
Quality serviceQuality =QoS_BACKGROUND);
protected:
void activateTracing();
void disableTracing(); ///< EX_FREE
friend class EngineDiagnostics;
};

View file

@ -7,6 +7,14 @@ return: 0
END
PLANNED "Engine Interface basics" EngineInterface_test <<END
END
PLANNED "Engine calculation streams" CalcStream_test <<END
END
PLANNED "Proc Node basics" NodeBasic_test <<END
END

7
tests/47playout.tests Normal file
View file

@ -0,0 +1,7 @@
TESTING "Component Test Suite: Player and Output" ./test-components --group=player
PLANNED "Output Slot Protocol" OutputSlotProtocol_test <<END
return: 0
END

View file

@ -0,0 +1,76 @@
/*
CalcStream(Test) - detailed coverage of engine calculation streams
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/error.hpp"
#include "proc/engine/engine-service.hpp"
//#include <boost/scoped_ptr.hpp>
//#include <iostream>
//#include <ctime>
using test::Test;
//using std::cout;
//using std::rand;
namespace proc {
namespace engine{
namespace test {
namespace { // test fixture...
} // (End) test fixture
/*******************************************************************
* @test detailed coverage of the various CalcStream flavours
* supported by the render engine interface.
*
* @todo WIP-WIP-WIP
*
* @see EngineInterface_test for the plain flat standard case
* @see EngineService
* @see CalcStream
* @see OutputSlotProtocol_test
*/
class CalcStream_test : public Test
{
virtual void
run (Arg)
{
UNIMPLEMENTED ("in-depth coverage of calculation streams");
}
};
/** Register this test class... */
LAUNCHER (CalcStream_test, "function engine");
}}} // namespace proc::engine::test

View file

@ -0,0 +1,111 @@
/*
EngineInterface(Test) - verify basics of the engine (scheduling) service
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/error.hpp"
#include "proc/engine/calc-stream.hpp"
#include "proc/engine/engine-service.hpp"
#include "proc/engine/engine-diagnostics.hpp"
#include "proc/play/diagnostic-output-slot.hpp"
#include "proc/mobject/model-port.hpp"
#include "proc/asset/pipe.hpp"
//#include <boost/scoped_ptr.hpp>
//#include <iostream>
//#include <ctime>
using test::Test;
//using std::cout;
//using std::rand;
namespace proc {
namespace engine{
namespace test {
using asset::Pipe;
using asset::PPipe;
using mobject::ModelPort;
typedef asset::ID<Pipe> PID;
namespace { // test fixture...
} // (End) test fixture
/*******************************************************************
* @test cover the basic service exposed at the engine interface:
* create a calculation stream and verify the translation
* into individual jobs.
*
* This test relies on the engine's diagnostic facilities, allowing
* to log and verify the generated jobs without needing to execute
* them. So this test doesn't actually run the engine. There are
* \link OutputSlotProtocol_test other tests \endlink covering
* the output generation separate from the engine.
*
* @see CalcStream_test more in-depth coverage of the various
* flavours of calculation streams supported by the engine
* @see EngineService
* @see CalcStream
* @see OutputSlotProtocol_test
*/
class EngineInterface_test : public Test
{
virtual void
run (Arg)
{
UNIMPLEMENTED ("simple standard case of Engine interface usage");
EngineService& engine = EngineService::instance();
EngineDiagnostics monitor(engine);
PID pipe = Pipe::query("id(dummy)");
ModelPort port(pipe);
OutputSlot& oSlot = DiagnosticOutputSlot::build();
Allocation output = oSlot.allocate();
Timings timings; /////////TODO
// Invoke test subject...
CalcStream calc = engine.calculate(port, timings, output);
////TODO some direct checks on the calculation stream??
CHECK (monitor.has_scheduled_jobs_for(timings));
}
};
/** Register this test class... */
LAUNCHER (EngineInterface_test, "function engine");
}}} // namespace proc::engine::test

View file

@ -1916,7 +1916,7 @@ To support this usage pattern, the Fixture implementation makes use of the [[PIm
* moreover, this necessitates a tight integration down to implementation level, both with the clean-up and the render processes themselves
</pre>
</div>
<div title="FixtureStorage" modifier="Ichthyostega" modified="201108141647" created="201012140231" tags="Builder impl operational draft" changecount="34">
<div title="FixtureStorage" modifier="Ichthyostega" modified="201108142259" created="201012140231" tags="Builder impl operational draft" changecount="35">
<pre>The Fixture &amp;rarr; [[data structure|FixtureDatastructure]] acts as umbrella to hook up the elements of the render engine's processing nodes network (LowLevelModel).
Each segment within the [[Segmentation]] of any timeline serves as ''extent'' or unit of memory management: it is built up completely during the corresponding build process and becomes immutable thereafter, finally to be discarded as a whole when superseded by a modified version of that segment (new build process) -- but only after all related render processes (&amp;rarr; CalcStream) are known to be terminated.
@ -1934,7 +1934,7 @@ Basically the concern is that each new CalcStream had to access the shared count
There are. As the builder is known to be run again and again, no one forces us to deallocate as soon as we could. That's the classical argument exploited by any garbage collector too. Thus we could just note the fact that a calculation stream is done and re-evaluate all those noted results on later occasion.
!!exploiting the frame-dispatch step
Irrespective of the decision in favour or against ref-counting, it seems reasonable to make use of the //frame dispatch step,// which is necessary anyway. The idea is to give each render process / a //copy//&amp;nbsp; of an dispatcher table object -- basically just a list of time breaking points and a pointer to the relevant exit node. If we keep track of those dispatcher tables, add a back-link to identify the process and require the process in turn to deregister, we get a tracking of tainted processes for free.
Irrespective of the decision in favour or against ref-counting, it seems reasonable to make use of the //frame dispatch step,// which is necessary anyway. The idea is to give each render process (maybe even each CalcStram) a //copy//&amp;nbsp; of an dispatcher table object -- basically just a list of time breaking points and a pointer to the relevant exit node. If we keep track of those dispatcher tables, add a back-link to identify the process and require the process in turn to deregister, we get a tracking of tainted processes for free.
!!assessment {{red{WIP 12/10}}}
But the primary question here is to judge the impact of such an implementation. What would be the costs?