diff --git a/src/proc/engine/diagnostic-buffer-provider.cpp b/src/proc/engine/diagnostic-buffer-provider.cpp new file mode 100644 index 000000000..69df7c35a --- /dev/null +++ b/src/proc/engine/diagnostic-buffer-provider.cpp @@ -0,0 +1,202 @@ +/* + DiagnosticBufferProvider - helper for testing against the BufferProvider interface + + Copyright (C) Lumiera.org + 2011, Hermann Vosseler + + 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 "include/logging.h" +#include "lib/meta/function.hpp" +#include "lib/scoped-ptrvect.hpp" + +#include "proc/engine/diagnostic-buffer-provider.hpp" + +#include +//#include + +using lib::ScopedPtrVect; +using boost::scoped_array; + + + +namespace engine { + + + /** Storage for the diagnostics frontend */ + lib::Singleton DiagnosticBufferProvider::diagnostics; + + + class Block + : boost::noncopyable + { + size_t size_; + scoped_array storage_; + + bool was_locked_; + + public: + Block() + : size_(0) + , storage_() + , was_locked_(false) + { } + + bool + was_used() const + { + return was_locked_; + } + }; + + + + namespace { // Details of allocation and accounting + + using lumiera::typelist::FunctionSignature; + using std::tr1::placeholders::_1; + using std::tr1::function; + using std::tr1::bind; + + /** + * type rebinding template for issuing flexible queries + * and forwarding them to the individual block entries + */ + template + struct _Query + { + typedef typename FunctionSignature::Ret Result; + }; + + function QUERY_was_used = bind (&Block::was_used, _1 ); + + } // (END) Details of allocation and accounting + + + + /** + * @internal DiagnosticBufferProvider's PImpl. + * Uses a linearly growing table of heap allocated buffer blocks, + * which will never be discarded, unless the PImpl is discarded as a whole. + * This way, the tracked usage information remains available after the fact. + */ + class DiagnosticBufferProvider::HeapMemProvider + : public BufferProvider + , public ScopedPtrVect + { + virtual BuffHandle + lockBufferFor (BufferDescriptor const& descriptor) + { + UNIMPLEMENTED ("lock buffer for exclusive use"); + } + + virtual void + releaseBuffer (BuffHandle const& handle) + { + UNIMPLEMENTED ("release a buffer and invalidate the handle"); + } + + public: + HeapMemProvider() + { + } + + virtual ~HeapMemProvider() + { + INFO (proc_mem, "discarding %uz diagnostic buffer entries", HeapMemProvider::size()); + } + + template + typename _Query::Result + accessStats (uint bufferID, FUN queryFunction) + { + queryFunction (access_or_create (bufferID)); + } + + private: + Block& + access_or_create (uint bufferID) + { + UNIMPLEMENTED ("either get existing block or create new entries to fit"); + } + }; + + + + BufferProvider& + DiagnosticBufferProvider::build() + { + return diagnostics().reset(); + } + + + DiagnosticBufferProvider& + DiagnosticBufferProvider::access (BufferProvider const& provider) + { + if (!diagnostics().isCurrent (provider)) + throw error::Invalid("given Provider doesn't match (current) diagnostic data record." + "This might be an lifecycle error. Did you build() this instance beforehand?"); + + return diagnostics(); + } + + + + + DiagnosticBufferProvider::HeapMemProvider& + DiagnosticBufferProvider::reset() + { + pImpl_.reset(new HeapMemProvider()); + return *pImpl_; + } + + bool + DiagnosticBufferProvider::isCurrent (BufferProvider const& implInstance) + { + return &implInstance == pImpl_.get(); + } + + + + + + /* === diagnostic API === */ + + bool + DiagnosticBufferProvider::buffer_was_used (uint bufferID) const + { + pImpl_->accessStats (bufferID, QUERY_was_used); + } + + + bool + DiagnosticBufferProvider::buffer_was_closed (uint bufferID) const + { + UNIMPLEMENTED ("check closed-flag of a specific buffer"); + } + + + void* + DiagnosticBufferProvider::accessStorage (uint bufferID) const + { + + } + + +} // namespace engine diff --git a/src/proc/engine/diagnostic-buffer-provider.hpp b/src/proc/engine/diagnostic-buffer-provider.hpp index c8836b617..399f7d782 100644 --- a/src/proc/engine/diagnostic-buffer-provider.hpp +++ b/src/proc/engine/diagnostic-buffer-provider.hpp @@ -31,13 +31,18 @@ #include "lib/error.hpp" +#include "lib/singleton.hpp" +#include "lib/util.hpp" #include "proc/engine/buffer-provider.hpp" +#include #include namespace engine { + namespace error = lumiera::error; + /******************************************************************** * Helper for unit tests: Buffer provider reference implementation. @@ -45,34 +50,29 @@ namespace engine { * @todo write type comment */ class DiagnosticBufferProvider - : public BufferProvider + : boost::noncopyable { + /** + * simple BufferProvider implementation + * with additional allocation tracking + */ + class HeapMemProvider; - /* === BufferProvider Implementation === */ - virtual BuffHandle - lockBufferFor (BufferDescriptor const& descriptor) - { - UNIMPLEMENTED ("lock buffer for exclusive use"); - } + boost::scoped_ptr pImpl_; + static lib::Singleton diagnostics; - virtual void - releaseBuffer (BuffHandle const& handle) - { - UNIMPLEMENTED ("release a buffer and invalidate the handle"); - } + + HeapMemProvider& reset(); + bool isCurrent (BufferProvider const&); 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"); - } + static BufferProvider& build(); /** access the diagnostic API of the buffer provider @@ -80,33 +80,21 @@ namespace engine { * for diagnostic access or wasn't registered beforehand. */ static DiagnosticBufferProvider& - access (BufferProvider const& provider) - { - UNIMPLEMENTED ("access existing instance linked to the given provider"); - } + access (BufferProvider const&); /* === diagnostic API === */ - bool - buffer_was_used (uint bufferID) - { - UNIMPLEMENTED ("check usage flag of a specific buffer"); - } - - - bool - buffer_was_closed (uint bufferID) - { - UNIMPLEMENTED ("check closed-flag of a specific buffer"); - } + bool buffer_was_used (uint bufferID) const; + bool buffer_was_closed (uint bufferID) const; + void* accessStorage (uint bufferID) const; template bool - object_was_attached (uint bufferID) + object_was_attached (uint bufferID) const { UNIMPLEMENTED ("verify object attachment status of a specific buffer"); } @@ -114,19 +102,12 @@ namespace engine { template bool - object_was_destroyed (uint bufferID) + object_was_destroyed (uint bufferID) const { UNIMPLEMENTED ("verify object attachment status of a specific buffer"); } - void* - accessStorage (uint bufferID) - { - - } - - private: