test driven brainstorming: using a BufferProvider
This commit is contained in:
parent
8016547d9c
commit
1f13931640
4 changed files with 195 additions and 2 deletions
67
src/proc/engine/diagnostic-buffer-provider.hpp
Normal file
67
src/proc/engine/diagnostic-buffer-provider.hpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
DIAGNOSTIC-BUFFER-PROVIDER.hpp - helper for testing against the BufferProvider interface
|
||||
|
||||
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 diagnostic-buffer-provider.hpp
|
||||
** An facility for writing unit-tests targetting the BufferProvider interface.
|
||||
**
|
||||
** @see buffer-provider-protocol-test.cpp
|
||||
*/
|
||||
|
||||
#ifndef PROC_ENGINE_DIAGNOSTIC_BUFFR_PROVIDER_H
|
||||
#define PROC_ENGINE_DIAGNOSTIC_BUFFR_PROVIDER_H
|
||||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "proc/engine/buffer-provider.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
|
||||
namespace engine {
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* Helper for unit tests: Buffer provider reference implementation.
|
||||
*
|
||||
* @todo write type comment
|
||||
*/
|
||||
class DiagnosticBufferProvider
|
||||
: public BufferProvider
|
||||
{
|
||||
public:
|
||||
/** build a new Diagnostic Buffer Provider instance,
|
||||
* discard the existing one. Use the static query API
|
||||
* for investigating collected data. */
|
||||
static BufferProvider&
|
||||
build()
|
||||
{
|
||||
UNIMPLEMENTED ("Diagnostic Buffer Provider instance");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace engine
|
||||
#endif
|
||||
|
|
@ -2,6 +2,11 @@ TESTING "Component Test Suite: Render Engine parts" ./test-components --group=en
|
|||
|
||||
|
||||
|
||||
PLANNED "BufferProviderProtocol_test" Buffer provider diagnostics <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
PLANNED "BuffTable_test" BuffTable_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
|
|
|||
121
tests/components/proc/engine/buffer-provider-protocol-test.cpp
Normal file
121
tests/components/proc/engine/buffer-provider-protocol-test.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
BufferProviderProtocol(Test) - demonstration of buffer provider usage cycle
|
||||
|
||||
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/error.hpp"
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
//#include "proc/play/diagnostic-output-slot.hpp"
|
||||
#include "proc/engine/diagnostic-buffer-provider.hpp"
|
||||
#include "proc/engine/buffhandle.hpp"
|
||||
|
||||
//#include <boost/format.hpp>
|
||||
//#include <iostream>
|
||||
|
||||
//using boost::format;
|
||||
//using std::string;
|
||||
//using std::cout;
|
||||
|
||||
|
||||
namespace engine{
|
||||
namespace test {
|
||||
|
||||
// using lib::AllocationCluster;
|
||||
// using mobject::session::PEffect;
|
||||
using ::engine::BuffHandle;
|
||||
using lumiera::error::LUMIERA_ERROR_LIFECYCLE;
|
||||
|
||||
|
||||
namespace { // Test fixture
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* @test verify the OutputSlot interface and base implementation
|
||||
* by performing full data exchange cycle. This is a
|
||||
* kind of "dry run" for documentation purposes,
|
||||
* both the actual OutputSlot implementation
|
||||
* as the client using this slot are Mocks.
|
||||
*/
|
||||
class BufferProviderProtocol_test : public Test
|
||||
{
|
||||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
UNIMPLEMENTED ("build a diagnostic buffer provider and perform a full lifecycle");
|
||||
verifyStandardCase();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
verifySimpleUsage()
|
||||
{
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #829
|
||||
// Create Test fixture.
|
||||
// In real usage, a suitable memory/frame/buffer provider
|
||||
// will be preconfigured, depending on the usage context
|
||||
BufferProvider& provider = DiagnosticBufferProvider::build();
|
||||
|
||||
BuffHandle buff = provider.lockBufferFor<TestFrame>();
|
||||
CHECK (buff.isValid());
|
||||
CHECK (sizeof(TestFrame) <= buff.size());
|
||||
buff.create<TestFrame>() = testData(0);
|
||||
|
||||
TestFrame* storage = *buff;
|
||||
CHECK (testData(0) == *storage);
|
||||
|
||||
buff.release();
|
||||
CHECK (!buff.isValid());
|
||||
VERIFY_ERROR (LIFECYCLE, *buff );
|
||||
|
||||
DiagnosticBufferProvider checker = DiagnosticBufferProvider::access(provider);
|
||||
CHECK (checker.buffer_was_used (0));
|
||||
CHECK (checker.buffer_was_closed (0));
|
||||
CHECK (checker.object_was_attached<TestFrame> ());
|
||||
CHECK (checker.object_was_destroyed<TestFrame> ());
|
||||
|
||||
CHECK (testData(0) == checker.accessStorage (0));
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #829
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
verifyStandardCase()
|
||||
{
|
||||
// Create Test fixture.
|
||||
// In real usage, a suitable memory/frame/buffer provider
|
||||
// will be preconfigured, depending on the usage context
|
||||
BufferProvider& provider = DiagnosticBufferProvider::build();
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #829
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #829
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (BufferProviderProtocol_test, "unit player");
|
||||
|
||||
|
||||
|
||||
}} // namespace engine::test
|
||||
|
|
@ -1121,7 +1121,7 @@ Mostly, the //client code,// i.e. code in need of using buffers, can access some
|
|||
|
||||
</pre>
|
||||
</div>
|
||||
<div title="BufferProvider" modifier="Ichthyostega" modified="201109151410" created="201107082330" tags="Rendering spec draft" changecount="12">
|
||||
<div title="BufferProvider" modifier="Ichthyostega" modified="201109162209" created="201107082330" tags="Rendering spec draft" changecount="13">
|
||||
<pre>It turns out that -- throughout the render engine implementation -- we never need direct access to the buffers holding media data. Buffers are just some entity to be //managed,// i.e. "allocated", "locked" and "released"; the //actual meaning of these operations can be left to the implementation.// The code within the render engine just pushes around ''smart-prt like handles''. These [[buffer handles|BuffHandle]] act as a front-end, being created by and linked to a buffer provider implementation. There is no need to manage the lifecycle of buffers automatically, because the use of buffers is embedded into the render calculation cycle, which follows a rather strict protocol anyway. Relying on the [[capabilities of the scheduler|SchedulerRequirements]], the sequence of individual jobs in the engine ensures...
|
||||
* that the availability of a buffer was ensured prior to planning a job ("buffer allocation")
|
||||
* that a buffer handle was obtained ("locked") prior to any operation requiring a buffer
|
||||
|
|
@ -1132,7 +1132,7 @@ While BufferProvider is an interface meant to be backed by various different kin
|
|||
;announcing
|
||||
:client code may announce beforehand that it expects to get a certain amount of buffers. Usually this causes some allocations (or similar mechanisms to ensure the avialability) to happen right away; the BufferProvider will then return the actual number of buffers guraanteed to be available. This announcing step is optional an can happen anytime before or even after using the buffers and it can be repeated with different values to adjust to changing requirements. (Currently 9/2011 this is meant to be global for the whole BufferProvider, but it might happen that we need to break that down to individual clients)
|
||||
;locking
|
||||
:this operation actually makes a buffer available for a specific client and returns a [[buffer handle|BuffHandle]]. The corresponding buffer is marked as used and can't be locked again until released. If necessary, the BufferProvider might at that point allocate memory to accomodate (especially when the buffers weren't announced beforehand). The locking might fail and raise an exception. To support additional sanity checks, the client may provide a token-ID with the lock-operation. This token may be retrieved later and it may be used to ensure the buffer is actually locked for //this token.//
|
||||
:this operation actually makes a buffer available for a specific client and returns a [[buffer handle|BuffHandle]]. The corresponding buffer is marked as used and can't be locked again until released. If necessary, at that point the BufferProvider might allocate memory to accomodate (especially when the buffers weren't announced beforehand). The locking may fail and raise an exception. You may expect failure to be unlikely when buffers have been //anounced beforehand.// To support additional sanity checks, the client may provide a token-ID with the lock-operation. This token may be retrieved later and it may be used to ensure the buffer is actually locked for //this token.//
|
||||
;attaching
|
||||
:optionally the client may attach an object to a locked buffer. This object is placement-constructed into the buffer and will be automatically destroyed when releasing the buffer. Alternatively, the client may provide a pair of constructor- / destructor-functors, which will be invoked in a similar manner. This allows e.g. to install descriptor structures within the buffer, as required by an external library.
|
||||
;releasing
|
||||
|
|
|
|||
Loading…
Reference in a new issue