idea how to crack the (daunting) problem regarding mutator storage
basically we'll establish a collaboration where both sides know only the interface (contract) of the partner; a safe margin for allocation size has to be established through metaprogramming (TODO)
This commit is contained in:
parent
7b73aa6950
commit
d2e7e1e06d
7 changed files with 215 additions and 42 deletions
|
|
@ -395,6 +395,24 @@ namespace diff{
|
|||
}
|
||||
}
|
||||
|
||||
/** locate element already accepted into the taget sequence
|
||||
* and assigne the designated payload value to it. */
|
||||
virtual bool
|
||||
assignElm (GenNode const& spec)
|
||||
{
|
||||
UNIMPLEMENTED("locate and assign");
|
||||
return false;
|
||||
}
|
||||
|
||||
/** locate the designated target element and build a suittable
|
||||
* sub-mutator for this element into the provided target buffer */
|
||||
virtual bool
|
||||
mutateChild (GenNode const& spec, TreeMutator::MutatorBuffer targetBuff)
|
||||
{
|
||||
UNIMPLEMENTED("locate and open sub mutator");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
TestWireTap(Target& dummy, PAR const& chain)
|
||||
: PAR(chain)
|
||||
|
|
|
|||
|
|
@ -327,19 +327,19 @@ namespace diff{
|
|||
}
|
||||
|
||||
void
|
||||
locate_and_assign (GenNode const& n)
|
||||
assignElm (GenNode const& n)
|
||||
{
|
||||
UNIMPLEMENTED("locate allready accepted element and assign given new payload");
|
||||
}
|
||||
|
||||
void
|
||||
locate_and_openSubScope (GenNode const& n)
|
||||
open_subScope (GenNode const& n)
|
||||
{
|
||||
UNIMPLEMENTED("locate allready accepted element and open recursive sub-scope for mutation");
|
||||
}
|
||||
|
||||
void
|
||||
closeSubScope()
|
||||
close_subScope()
|
||||
{
|
||||
UNIMPLEMENTED("finish and leave sub scope and return to invoking parent scope");
|
||||
}
|
||||
|
|
@ -401,14 +401,14 @@ namespace diff{
|
|||
virtual void
|
||||
set (GenNode const& n) override
|
||||
{
|
||||
locate_and_assign (n);
|
||||
assignElm (n);
|
||||
}
|
||||
|
||||
/** open nested scope to apply diff to child object */
|
||||
virtual void
|
||||
mut (GenNode const& n) override
|
||||
{
|
||||
locate_and_openSubScope (n);
|
||||
open_subScope (n);
|
||||
|
||||
Rec const& childRecord = child.data.get<Rec>();
|
||||
TRACE (diff, "tree-diff: ENTER scope %s", cStr(childRecord));
|
||||
|
|
@ -421,7 +421,7 @@ namespace diff{
|
|||
TRACE (diff, "tree-diff: LEAVE scope %s", cStr(describeScope()));
|
||||
|
||||
__expect_end_of_scope (n.idi);
|
||||
closeSubScope();
|
||||
close_subScope();
|
||||
__expect_valid_parent_scope (n.idi);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,16 +72,67 @@
|
|||
#include "lib/error.hpp"
|
||||
#include "lib/symbol.hpp"
|
||||
#include "lib/diff/gen-node.hpp"
|
||||
#include "lib/opaque-holder.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
//#include "lib/format-string.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <utility> ////TODO
|
||||
#include <string>
|
||||
//#include <vector>
|
||||
//#include <map>
|
||||
|
||||
|
||||
namespace lib {
|
||||
/////////////////////////////TODO move over into opaque-holder.hpp
|
||||
/**
|
||||
* handle to allow for safe _»remote implantation«_
|
||||
* of an unknown subclass into a given OpaqueHolder buffer,
|
||||
* without having to disclose the concrete buffer type or size.
|
||||
* @remarks this is especially geared towards use in APIs, allowing
|
||||
* a not yet known implementation to implant an agent or collaboration
|
||||
* partner into the likewise undisclosed innards of the exposed service.
|
||||
* @warning the type BA must expose a virtual dtor, since the targetted
|
||||
* OpaqueHolder has to take ownership of the implanted object.
|
||||
*/
|
||||
template<class BA>
|
||||
class PlantingHandle
|
||||
{
|
||||
void* buffer_;
|
||||
size_t maxSiz_;
|
||||
|
||||
///////TODO static assert to virtual dtor??
|
||||
public:
|
||||
template<size_t maxSiz>
|
||||
PlantingHandle (OpaqueHolder<BA, maxSiz>& targetBuffer)
|
||||
: buffer_(&targetBuffer)
|
||||
, maxSiz_(maxSiz_)
|
||||
{ }
|
||||
|
||||
|
||||
template<class SUB, typename...ARGS>
|
||||
BA&
|
||||
create (ARGS&& ...args)
|
||||
{
|
||||
if (sizeof(SUB) > maxSiz_)
|
||||
throw error::Fatal("Unable to implant implementation object of size "
|
||||
"exceeding the pre-established storage buffer capacity."
|
||||
,error::LUMIERA_ERROR_CAPACITY);
|
||||
|
||||
using Holder = OpaqueHolder<BA, sizeof(SUB)>;
|
||||
Holder& holder = *static_cast<Holder*> (buffer_);
|
||||
|
||||
return holder.create<SUB> (std::forward<ARGS> (args)...);
|
||||
}
|
||||
|
||||
template<class SUB>
|
||||
bool
|
||||
canCreate() const
|
||||
{
|
||||
return sizeof(SUB) <= maxSiz_;
|
||||
}
|
||||
};
|
||||
/////////////////////////////TODO move over into opaque-holder.hpp
|
||||
namespace diff{
|
||||
|
||||
namespace error = lumiera::error;
|
||||
|
|
@ -92,6 +143,8 @@ namespace diff{
|
|||
using std::string;
|
||||
|
||||
|
||||
|
||||
|
||||
class TestMutationTarget; // for unit testing
|
||||
|
||||
|
||||
|
|
@ -166,10 +219,31 @@ namespace diff{
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual TreeMutator&
|
||||
mutateChild (ID id)
|
||||
/** locate the designated target element
|
||||
* (must be already accepted into the target sequence).
|
||||
* Perform an assignement with the given payload value
|
||||
* @throw when assignement fails (typically error::Logic)
|
||||
* @return false when unable to locate the target */
|
||||
virtual bool
|
||||
assignElm (GenNode const&)
|
||||
{
|
||||
UNIMPLEMENTED("expose a recursive TreeMutator to transform the denoted child");
|
||||
// do nothing by default
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
using MutatorBuffer = PlantingHandle<TreeMutator>;
|
||||
|
||||
/** locate the designated target element
|
||||
* and build a suittable sub-mutator for this element
|
||||
* into the provided target buffer
|
||||
* @throw error::Fatal when buffer is insufficient
|
||||
* @return false when unable to locate the target */
|
||||
virtual bool
|
||||
mutateChild (GenNode const&, MutatorBuffer)
|
||||
{
|
||||
// do nothing by default
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void setAttribute (ID, Attribute&) { /* do nothing by default */ }
|
||||
|
|
|
|||
|
|
@ -490,7 +490,7 @@ namespace lib {
|
|||
* The whole compound is copyable if and only if the contained
|
||||
* object is copyable.
|
||||
*
|
||||
* \par using OpaqueHolder
|
||||
* ## using OpaqueHolder
|
||||
* OpaqueHolder instances are copyable value objects. They are created
|
||||
* either empty, by copy from an existing OpaqueHolder, or by directly
|
||||
* specifying the concrete object to embed. This target object will be
|
||||
|
|
@ -500,16 +500,19 @@ namespace lib {
|
|||
* Later on, the embedded value might be accessed
|
||||
* - using the smart-ptr-like access through the common base interface BA
|
||||
* - when knowing the exact type to access, the templated #get might be an option
|
||||
* - the empty state of the container and a \c isValid() on the target may be checked
|
||||
* - a combination of both is available as a \c bool check on the OpaqueHolder instance.
|
||||
* - the empty state of the container and a `isValid()` on the target may be checked
|
||||
* - a combination of both is available as a `bool` check on the OpaqueHolder instance.
|
||||
*
|
||||
* For using OpaqueHolder, several \b assumptions need to be fulfilled
|
||||
* For using OpaqueHolder, several *assumptions* need to be fulfilled
|
||||
* - any instance placed into OpaqueHolder is below the specified maximum size
|
||||
* - the caller cares for thread safety. No concurrent get calls while in mutation!
|
||||
*
|
||||
* @tparam BA the nominal Base/Interface class for a family of types
|
||||
* @tparam siz maximum storage required for the targets to be held inline
|
||||
*/
|
||||
template
|
||||
< class BA ///< the nominal Base/Interface class for a family of types
|
||||
, size_t siz = sizeof(BA) ///< maximum storage required for the targets to be held inline
|
||||
< class BA
|
||||
, size_t siz = sizeof(BA)
|
||||
>
|
||||
class OpaqueHolder
|
||||
: public InPlaceAnyHolder<siz, InPlaceAnyHolder_useCommonBase<BA> >
|
||||
|
|
@ -568,11 +571,15 @@ namespace lib {
|
|||
* and especially it is mandatory for the base class to provide a
|
||||
* virtual dtor. On the other hand, just the (alignment rounded)
|
||||
* storage for the object(s) placed into the buffer is required.
|
||||
*
|
||||
* @tparam BA the nominal Base/Interface class for a family of types
|
||||
* @tparam siz maximum storage required for the targets to be held inline
|
||||
* @tparam DEFAULT the default instance to place initially
|
||||
*/
|
||||
template
|
||||
< class BA ///< the nominal Base/Interface class for a family of types
|
||||
, size_t siz = sizeof(BA) ///< maximum storage required for the targets to be held inline
|
||||
, class DEFAULT = BA ///< the default instance to place initially
|
||||
< class BA
|
||||
, size_t siz = sizeof(BA)
|
||||
, class DEFAULT = BA
|
||||
>
|
||||
class InPlaceBuffer
|
||||
: boost::noncopyable
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
** number of objects is (heap) allocated right away, but no objects are
|
||||
** created. Later on, individual objects are "pushed" into the collection
|
||||
** by invoking #appendNewElement() to create a new element of the default
|
||||
** type I) or #appendNew<Type>(args) to create some subtype. This way,
|
||||
** type `I`) or #appendNew<Type>(args) to create some subtype. This way,
|
||||
** the container is being filled successively.
|
||||
** - the "RAII style" usage strives to create all of the content objects
|
||||
** right away, immediately after the memory allocation. This usage pattern
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
** @note intentionally there is no operation to discard individual objects,
|
||||
** all you can do is to #clear() the whole container.
|
||||
** @note the container can hold instances of a subclass of the type defined
|
||||
** by the template parameter I. But you need to ensure in this case
|
||||
** by the template parameter `I`. But you need to ensure in this case
|
||||
** that the defined buffer size for each element (2nt template parameter)
|
||||
** is sufficient to hold any of these subclass instances. This condition
|
||||
** is protected by a static assertion (compilation failure).
|
||||
|
|
@ -93,10 +93,12 @@ namespace lib {
|
|||
* All child objects reside in a common chunk of storage
|
||||
* and are owned and managed by this collection holder.
|
||||
* Array style access and iteration is provided.
|
||||
* @tparam I the nominal Base/Interface class for a family of types
|
||||
* @tparam siz maximum storage required for the targets to be held inline
|
||||
*/
|
||||
template
|
||||
< class I ///< the nominal Base/Interface class for a family of types
|
||||
, size_t siz = sizeof(I) ///< maximum storage required for the targets to be held inline
|
||||
< class I
|
||||
, size_t siz = sizeof(I)
|
||||
>
|
||||
class ScopedCollection
|
||||
: boost::noncopyable
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@
|
|||
** supporting dynamic growth (like in std::vector#resize() ) additionally
|
||||
** requires a facility to transfer the lifecycle management control between
|
||||
** holder instances. This is the purpose of the \c transfer_control
|
||||
** friend function.
|
||||
** friend function.
|
||||
**
|
||||
** @deprecated this is a pre C++11 concept and superseded by rvalue references
|
||||
**
|
||||
** @see scoped-holder-test.cpp
|
||||
** @see scoped-holder-transfer.hpp use in std::vector
|
||||
|
|
|
|||
|
|
@ -899,39 +899,102 @@
|
|||
<node CREATED="1455928166683" ID="ID_1779120290" MODIFIED="1455928691589" TEXT="accept_until">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<node CREATED="1455928383765" ID="ID_1859031782" MODIFIED="1455928389737" TEXT="accept until condition is met"/>
|
||||
<node CREATED="1457120353283" ID="ID_997608114" MODIFIED="1457120364470" TEXT="meta operation"/>
|
||||
<node COLOR="#e5500c" CREATED="1457120353283" ID="ID_997608114" MODIFIED="1457190890254" TEXT="meta operation">
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
|
||||
</node>
|
||||
<node CREATED="1455927510666" ID="ID_14225718" MODIFIED="1455928690029" TEXT="locate">
|
||||
</node>
|
||||
<node CREATED="1455928184504" ID="ID_1474129407" MODIFIED="1457190163357" TEXT="assignElm">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<node CREATED="1455928393788" ID="ID_1084411962" MODIFIED="1455928398936" TEXT="locate by ID comparison">
|
||||
<node CREATED="1455928565869" ID="ID_197213145" MODIFIED="1455928572200" TEXT="incremental pos ref"/>
|
||||
<node CREATED="1455928573028" ID="ID_1321605846" MODIFIED="1455928576391" TEXT="ID"/>
|
||||
<node CREATED="1455928393788" ID="ID_1084411962" MODIFIED="1457190205367" TEXT="locate target">
|
||||
<node CREATED="1457190206827" ID="ID_897956826" MODIFIED="1457190220485" TEXT="allready accepted element"/>
|
||||
<node CREATED="1457190227089" ID="ID_265366260" MODIFIED="1457190234435" TEXT="find by ID comparison"/>
|
||||
<node CREATED="1457190235191" ID="ID_1385656813" MODIFIED="1457190240027" TEXT="try current element first"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1455928184504" ID="ID_1474129407" MODIFIED="1455928687942" TEXT="assign">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<node CREATED="1455928403931" ID="ID_1442292399" MODIFIED="1455928412462" TEXT="assign payload">
|
||||
<node CREATED="1455928583523" ID="ID_1874089052" MODIFIED="1455928585686" TEXT="pos ref"/>
|
||||
<node CREATED="1455928586506" ID="ID_567539648" MODIFIED="1455928611275" TEXT="Type context"/>
|
||||
<node CREATED="1455928586506" ID="ID_567539648" MODIFIED="1457190259104" TEXT="implicit Type context"/>
|
||||
<node CREATED="1455928612239" ID="ID_1377931073" MODIFIED="1455928619186" TEXT="embedded target data"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1455928189695" ID="ID_1518531652" MODIFIED="1455928686421" TEXT="mutator">
|
||||
<node CREATED="1455928189695" ID="ID_1518531652" MODIFIED="1457190272990" TEXT="buildMutator">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<node CREATED="1455928415161" ID="ID_316051704" MODIFIED="1455928425468" TEXT="build mutator for target">
|
||||
<node CREATED="1455928625269" ID="ID_1510952440" MODIFIED="1455928628073" TEXT="pos ref"/>
|
||||
<node CREATED="1457190279001" ID="ID_555722741" MODIFIED="1457190300305" TEXT="locate target">
|
||||
<node CREATED="1457190288624" ID="ID_688053219" MODIFIED="1457190296115" TEXT="same as in 'assignElm'"/>
|
||||
</node>
|
||||
<node CREATED="1455928415161" ID="ID_316051704" MODIFIED="1457190369739" TEXT="fabricate mutator">
|
||||
<node CREATED="1457190370846" ID="ID_914587366" MODIFIED="1457190374749" TEXT="suitable for target"/>
|
||||
<node CREATED="1455928625269" ID="ID_1510952440" MODIFIED="1457190388167" TEXT="open / init mutator"/>
|
||||
</node>
|
||||
<node CREATED="1457190320444" ID="ID_1175346415" MODIFIED="1457190328199" TEXT="place into provided buffer">
|
||||
<node CREATED="1457190396170" ID="ID_1295881596" MODIFIED="1457190419158">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<i>throw </i>when
|
||||
</p>
|
||||
<p>
|
||||
insufficent space
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1455928193863" ID="ID_879541123" MODIFIED="1455928685054" TEXT="push">
|
||||
</node>
|
||||
<node CREATED="1455928193863" ID="ID_879541123" MODIFIED="1457190610865" TEXT="open_subScope">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<node CREATED="1455928427432" ID="ID_1222674854" MODIFIED="1455928435275" TEXT="push mutator on stack">
|
||||
<node CREATED="1455928632684" ID="ID_1171317180" MODIFIED="1455928651005" TEXT="mutator or mutator ref"/>
|
||||
<node CREATED="1455928657257" ID="ID_914429679" MODIFIED="1455928668323" TEXT="Type context for stack frame"/>
|
||||
<node CREATED="1455928427432" ID="ID_1222674854" MODIFIED="1455928435275" TEXT="push mutator on stack"/>
|
||||
<node CREATED="1457190622236" ID="ID_589756146" MODIFIED="1457190641456">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
invoke <b>buildMutator</b>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node COLOR="#e5500c" CREATED="1457190642993" ID="ID_1140350120" MODIFIED="1457190901922" STYLE="fork" TEXT="meta operation">
|
||||
<edge COLOR="#808080" STYLE="bezier" WIDTH="thin"/>
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1455928198718" ID="ID_593000833" MODIFIED="1455928683343" TEXT="pop">
|
||||
<node CREATED="1455928198718" ID="ID_593000833" MODIFIED="1457190657851" TEXT="close_subScope">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<node CREATED="1455928440366" ID="ID_1859099649" MODIFIED="1455928446696" TEXT="pop previous mutator from stack"/>
|
||||
<node CREATED="1455928440366" ID="ID_1859099649" MODIFIED="1457190669578" TEXT="just pop mutator"/>
|
||||
<node CREATED="1457190670069" ID="ID_331099500" MODIFIED="1457190818805" TEXT="abandon mutator">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<b>NOTE</b>: mutator need to be written in such a way
|
||||
</p>
|
||||
<p>
|
||||
to be just discarded when done with the alterations.
|
||||
</p>
|
||||
<p>
|
||||
That is, the mutator<i> must not</i> incorporate the target data, rather it is expected
|
||||
</p>
|
||||
<p>
|
||||
to construct the new target data efficiently in place.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1457190826145" ID="ID_1231904441" MODIFIED="1457190834604" TEXT="return to previous mutator"/>
|
||||
<node COLOR="#e5500c" CREATED="1457190844318" ID="ID_614952113" MODIFIED="1457190936915" STYLE="fork" TEXT="meta operation">
|
||||
<edge COLOR="#808080" STYLE="bezier" WIDTH="thin"/>
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -1771,6 +1834,13 @@
|
|||
<node CREATED="1457119959408" ID="ID_275413703" MODIFIED="1457119961803" TEXT="sondern NOP"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1457227228502" ID="ID_845299775" MODIFIED="1457227233433" TEXT="sub-Mutator">
|
||||
<node CREATED="1457227237269" ID="ID_1175871622" MODIFIED="1457227296340" TEXT="wird über ein Handle implantiert">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1457227248779" ID="ID_1765753442" MODIFIED="1457227279155" TEXT="Implementierungs-Schicht kennt Typ"/>
|
||||
<node CREATED="1457227279703" ID="ID_347493370" MODIFIED="1457227288610" TEXT="aber Tree-Mutator übernimmt ownership"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1456528462585" HGAP="27" ID="ID_1770521063" MODIFIED="1457038563027" TEXT="Elemente" VSHIFT="12">
|
||||
|
|
|
|||
Loading…
Reference in a new issue