iterator exploring monad finished, passes unit test
This commit is contained in:
parent
3d0d599158
commit
e6a105fbc1
4 changed files with 130 additions and 22 deletions
|
|
@ -50,6 +50,24 @@
|
|||
** - and this evaluation needs to be done asynchronously and in parallel (no locking, immutable data)
|
||||
** - and a partial evaluation needs to be stored as continuation (not relying on the stack for partial results)
|
||||
**
|
||||
** \par preconfigured solutions
|
||||
** This header provides some preconfigured applications of this pattern
|
||||
** - the DefaultCombinator processes the source elements on demand, feeding them through
|
||||
** the given functor and using the resulting iterator to deliver the result elements
|
||||
** - Chained iterator uses similar building blocks just to get the "flattening" of
|
||||
** a sequence of iterators into a single result iterator
|
||||
** - the RecursiveExhaustingEvaluation is another kind of combination strategy,
|
||||
** which recursively evaluates the given function and combines the results
|
||||
** such as to produce classical depth-first and breadth-first search orders.
|
||||
**
|
||||
** Alternatively, just the basic IterExplorer template can be used together with a custom
|
||||
** "combinator strategy" to implement very specific and optimised data structure evaluation patterns.
|
||||
** This strategy needs to define some way to hold onto the original source elements, feed them through
|
||||
** the functor on demand and recombine the result sets into a new sequence to be delivered on demand.
|
||||
** Actually this is what we utilise for the continuous render job generation within the scheduler.
|
||||
** The preconfigured variants where created as proof-of-concept, to document and verify this
|
||||
** implementation technique as such.
|
||||
**
|
||||
** @see IterExplorer_test
|
||||
** @see iter-adapter.hpp
|
||||
** @see itertools.hpp
|
||||
|
|
@ -63,7 +81,6 @@
|
|||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
//#include "lib/bool-checkable.hpp"
|
||||
#include "lib/meta/function.hpp"
|
||||
#include "lib/iter-adapter.hpp"
|
||||
#include "lib/iter-stack.hpp"
|
||||
|
|
@ -71,7 +88,6 @@
|
|||
#include "lib/null-value.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
//#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <stack>
|
||||
|
||||
|
|
@ -240,10 +256,16 @@ namespace lib {
|
|||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace iter_explorer { ///< predefined policies and configurations
|
||||
|
||||
using util::unConst;
|
||||
|
|
@ -286,6 +308,7 @@ namespace lib {
|
|||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Building block: evaluate and combine a sequence of iterators.
|
||||
* This implementation helper provides two kinds of "buffers" (actually implemented
|
||||
|
|
@ -313,7 +336,7 @@ namespace lib {
|
|||
typedef typename ResultIter::value_type value_type;
|
||||
typedef typename ResultIter::reference reference;
|
||||
typedef typename ResultIter::pointer pointer;
|
||||
|
||||
|
||||
|
||||
CombinedIteratorEvaluation() { }
|
||||
|
||||
|
|
@ -474,6 +497,9 @@ namespace lib {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A "Combinator strategy" allowing to expand and evaluate a
|
||||
* (functional) data structure successively and recursively.
|
||||
|
|
@ -598,24 +624,29 @@ namespace lib {
|
|||
|
||||
|
||||
/**
|
||||
* Strategy for recursive exhausting \em depth-first evaluation.
|
||||
* Implemented using a heap-allocated stack of partially evaluated iterators.
|
||||
* The next evaluation step will happen at the iterator returned by #getFeed,
|
||||
* which is the most recently pushed intermediary result.
|
||||
* Strategy building block for recursive exhausting evaluation.
|
||||
* Allows to create depth-fist or breadth-first evaluation patters, just
|
||||
* by using a suitably intermediary storage container to hold the partially
|
||||
* evaluated iterators created at each evaluation step. Using a stack and
|
||||
* pushing results will create a depth-first pattern, while using a queue
|
||||
* will evaluate in layers (breadth-first). In both cases, the next
|
||||
* evaluation step will happen at the iterator returned by #getFeed.
|
||||
* @warning uses an empty-iterator marker object to signal exhaustion
|
||||
* - this marker \c IT() may be re-initialised concurrently
|
||||
* - accessing this marker during app shutdown might access
|
||||
* an already defunct object
|
||||
*/
|
||||
template<class IT>
|
||||
class DepthFirstEvaluationBuffer
|
||||
template< class IT
|
||||
, template<class> class _QUEUE_ ///< the actual container to use for storage of intermediary results
|
||||
>
|
||||
class EvaluationBufferStrategy
|
||||
{
|
||||
IterStack<IT> intermediaryResults_;
|
||||
_QUEUE_<IT> intermediaryResults_;
|
||||
|
||||
|
||||
/** @return default constructed (=empty) iterator
|
||||
* @remarks casting away const is safe here, since all
|
||||
* you can do with an NIL iterator is to test for emptiness.
|
||||
* you can do with an NIL iterator is to test for emptiness.
|
||||
*/
|
||||
IT &
|
||||
emptySequence()
|
||||
|
|
@ -641,13 +672,35 @@ namespace lib {
|
|||
void
|
||||
feedBack (IT const& newEvaluationResults)
|
||||
{
|
||||
intermediaryResults_.push (newEvaluationResults);
|
||||
intermediaryResults_.insert (newEvaluationResults);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* preconfigured IterExplorer "state core" resulting in depth-first exhaustive evaluation
|
||||
* concrete strategy for recursive \em depth-first evaluation.
|
||||
* Using heap allocated storage in a STL Deque (used stack-like)
|
||||
*/
|
||||
template<class IT>
|
||||
struct DepthFirstEvaluationBuffer
|
||||
: EvaluationBufferStrategy<IT, IterStack>
|
||||
{ };
|
||||
|
||||
/**
|
||||
* concrete strategy for recursive \em breadth-first evaluation.
|
||||
* Using heap allocated storage in a STL Deque (used queue-like)
|
||||
*/
|
||||
template<class IT>
|
||||
struct BreadthFirstEvaluationBuffer
|
||||
: EvaluationBufferStrategy<IT, IterQueue>
|
||||
{ };
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* preconfigured IterExplorer "state core" resulting in
|
||||
* depth-first exhaustive evaluation
|
||||
*/
|
||||
template<class SRC, class FUN>
|
||||
struct DepthFirstEvaluationConbinator
|
||||
|
|
@ -660,6 +713,21 @@ namespace lib {
|
|||
{ }
|
||||
};
|
||||
|
||||
/**
|
||||
* preconfigured IterExplorer "state core" resulting in
|
||||
* breadth-first exhaustive evaluation
|
||||
*/
|
||||
template<class SRC, class FUN>
|
||||
struct BreadthFirstEvaluationConbinator
|
||||
: RecursiveExhaustingEvaluation<SRC, FUN, BreadthFirstEvaluationBuffer>
|
||||
{
|
||||
BreadthFirstEvaluationConbinator() { }
|
||||
|
||||
BreadthFirstEvaluationConbinator(FUN explorerFunction, SRC const& sourceElements)
|
||||
: RecursiveExhaustingEvaluation<SRC, FUN, BreadthFirstEvaluationBuffer> (explorerFunction,sourceElements)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper template to bootstrap a chain of IterExplorers.
|
||||
|
|
@ -685,7 +753,7 @@ namespace lib {
|
|||
|
||||
|
||||
/* === Iteration control API for IterStateWrapper == */
|
||||
|
||||
|
||||
friend bool
|
||||
checkPoint (WrappedSequence const& sequence)
|
||||
{
|
||||
|
|
@ -716,12 +784,24 @@ namespace lib {
|
|||
{ }
|
||||
};
|
||||
|
||||
template<class SRC>
|
||||
struct BreadthFirst
|
||||
: IterExplorer<WrappedSequence<SRC>, BreadthFirstEvaluationConbinator>
|
||||
{
|
||||
BreadthFirst() { };
|
||||
BreadthFirst(SRC const& srcSeq)
|
||||
: IterExplorer<WrappedSequence<SRC>, BreadthFirstEvaluationConbinator> (srcSeq)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
}//(End) namespace iter_explorer : predefined policies and configurations
|
||||
|
||||
|
||||
|
||||
|
||||
/* ==== convenient builder free functions ==== */
|
||||
|
||||
template<class IT>
|
||||
inline IterExplorer<iter_explorer::WrappedSequence<IT> >
|
||||
exploreIter (IT const& srcSeq)
|
||||
|
|
@ -738,6 +818,14 @@ namespace lib {
|
|||
}
|
||||
|
||||
|
||||
template<class IT>
|
||||
inline iter_explorer::BreadthFirst<IT>
|
||||
breadthFirst (IT const& srcSeq)
|
||||
{
|
||||
return iter_explorer::BreadthFirst<IT> (srcSeq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class IT>
|
||||
inline iter_explorer::ChainedIters<IT>
|
||||
|
|
|
|||
|
|
@ -122,6 +122,13 @@ namespace lib {
|
|||
return *this;
|
||||
}
|
||||
|
||||
IterStack&
|
||||
insert (TY const& elm)
|
||||
{
|
||||
return push(elm);
|
||||
}
|
||||
|
||||
|
||||
TY
|
||||
pop()
|
||||
{
|
||||
|
|
@ -162,6 +169,12 @@ namespace lib {
|
|||
return *this;
|
||||
}
|
||||
|
||||
IterQueue&
|
||||
insert (TY const& elm)
|
||||
{
|
||||
return feed(elm);
|
||||
}
|
||||
|
||||
TY
|
||||
pop()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -508,11 +508,21 @@ out: values_4_key(::[0-9]{1,2})+
|
|||
END
|
||||
|
||||
|
||||
TEST "Iterator monad variations" IterExplorer_test
|
||||
out: 1-2-3-4-5-6-7-8
|
||||
out: 0-1-2-3-4-0-1-2-3-4-5-6-0-1-2-3-4-5-6-7-8
|
||||
out: 0-1-2-3-4-5-6-7-8
|
||||
out: 0-1-2-3-4-5-6-7-8
|
||||
END
|
||||
|
||||
|
||||
TEST "Stack-like iterator" IterStack_test
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "Queue-like iterator" IterQueue_test
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,8 +52,7 @@ namespace test{
|
|||
using lumiera::error::LUMIERA_ERROR_ITER_EXHAUST;
|
||||
|
||||
|
||||
namespace { // test material: simple number sequence iterator
|
||||
|
||||
namespace { // test substrate: simple number sequence iterator
|
||||
|
||||
/**
|
||||
* This iteration "state core" type describes
|
||||
|
|
@ -444,11 +443,9 @@ namespace test{
|
|||
void
|
||||
verifyBreadthFirstExploration ()
|
||||
{
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||
NumberSeries root = elements(30);
|
||||
string explorationResult = materialise (breadthFirst(root) >>= exploreChildren);
|
||||
CHECK (explorationResult == "30-6-10-15-2-3-2-5-3-5-1-1-1-1-1-1");
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue