Library: rework detection of ''same object''
We use the memory address to detect reference to ''the same language object.'' While primarily a testing tool, this predicate is also used in the core application at places, especially to prevent self-assignment and to handle custom allocations. It turns out that actually we need two flavours for convenient usage - `isSameObject` uses strict comparison of address and accepts only references - `isSameAdr` can also accept pointers and even void*, but will dereference pointers This leads to some further improvements of helper utilities related to memory addresses...
This commit is contained in:
parent
766da84a62
commit
7ed8486774
26 changed files with 731 additions and 359 deletions
321
research/try.cpp
321
research/try.cpp
|
|
@ -1,58 +1,18 @@
|
|||
/* try.cpp - for trying out some language features....
|
||||
/* try.cpp - to try out and experiment with new features....
|
||||
* scons will create the binary bin/try
|
||||
*
|
||||
*/
|
||||
|
||||
// 8/07 - how to control NOBUG??
|
||||
// execute with NOBUG_LOG='ttt:TRACE' bin/try
|
||||
// 1/08 - working out a static initialisation problem for Visitor (Tag creation)
|
||||
// 1/08 - check 64bit longs
|
||||
// 4/08 - comparison operators on shared_ptr<Asset>
|
||||
// 4/08 - conversions on the value_type used for boost::any
|
||||
// 5/08 - how to guard a downcasting access, so it is compiled in only if the involved types are convertible
|
||||
// 7/08 - combining partial specialisation and subclasses
|
||||
// 10/8 - abusing the STL containers to hold noncopyable values
|
||||
// 6/09 - investigating how to build a mixin template providing an operator bool()
|
||||
// 12/9 - tracking down a strange "warning: type qualifiers ignored on function return type"
|
||||
// 1/10 - can we determine at compile time the presence of a certain function (for duck-typing)?
|
||||
// 4/10 - pretty printing STL containers with python enabled GDB?
|
||||
// 1/11 - exploring numeric limits
|
||||
// 1/11 - integer floor and wrap operation(s)
|
||||
// 1/11 - how to fetch the path of the own executable -- at least under Linux?
|
||||
// 10/11 - simple demo using a pointer and a struct
|
||||
// 11/11 - using the boost random number generator(s)
|
||||
// 12/11 - how to detect if string conversion is possible?
|
||||
// 1/12 - is partial application of member functions possible?
|
||||
// 5/14 - c++11 transition: detect empty function object
|
||||
// 7/14 - c++11 transition: std hash function vs. boost hash
|
||||
// 9/14 - variadic templates and perfect forwarding
|
||||
// 11/14 - pointer to member functions and name mangling
|
||||
// 8/15 - Segfault when loading into GDB (on Debian/Jessie 64bit
|
||||
// 8/15 - generalising the Variant::Visitor
|
||||
// 1/16 - generic to-string conversion for ostream
|
||||
// 1/16 - build tuple from runtime-typed variant container
|
||||
// 3/17 - generic function signature traits, including support for Lambdas
|
||||
// 9/17 - manipulate variadic templates to treat varargs in several chunks
|
||||
// 11/17 - metaprogramming to detect the presence of extension points
|
||||
// 11/17 - detect generic lambda
|
||||
// 12/17 - investigate SFINAE failure. Reason was indirect use while in template instantiation
|
||||
// 03/18 - Dependency Injection / Singleton initialisation / double checked locking
|
||||
// 04/18 - investigate construction of static template members
|
||||
// 08/18 - Segfault when compiling some regular expressions for EventLog search
|
||||
// 10/18 - investigate insidious reinterpret cast
|
||||
// 12/18 - investigate the trinomial random number algorithm from the C standard lib
|
||||
// 04/19 - forwarding tuple element(s) to function invocation
|
||||
// 06/19 - use a statefull counting filter in a treeExplorer pipeline
|
||||
// 03/20 - investigate type deduction bug with PtrDerefIter
|
||||
// 01/21 - look for ways to detect the presence of an (possibly inherited) getID() function
|
||||
// 08/22 - techniques to supply additional feature selectors to a constructor call
|
||||
// 10/23 - search for ways to detect signatures of member functions and functors uniformly
|
||||
// 11/23 - prototype for a builder-DSL to configure a functor to draw and map random values
|
||||
// 11/24 - how to define a bare object location comparison predicate
|
||||
// 11/23 - prototype for grouping from iterator
|
||||
|
||||
|
||||
/** @file try.cpp
|
||||
* Investigate how best to integrate a grouping device into the iterator pipeline framework.
|
||||
* Attempt to generalise the util::isSameObject, to support a mix of pointers and references.
|
||||
* This is a long standing requirement, yet I made several failed attempts in the past,
|
||||
* due to difficulties detecting a pointer after perfect-forwarding the argument. However,
|
||||
* it is not even necessary to perfect-forward, if all we want is to extract the raw address.
|
||||
*
|
||||
* To my defence, I should add that I never took the time to conduct a proper experiment
|
||||
* in a stand-alone setup; investigating directly in "lib/util.hpp" is a waste of time.
|
||||
*/
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
|
@ -61,186 +21,113 @@ typedef unsigned int uint;
|
|||
#include "lib/format-cout.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
#include "lib/test/diagnostic-output.hpp"
|
||||
#include "lib/format-util.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include "lib/iter-explorer.hpp"
|
||||
#include "lib/test/test-coll.hpp"
|
||||
#include <utility>
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
using std::forward;
|
||||
using lib::rani;
|
||||
using std::move;
|
||||
using std::string;
|
||||
|
||||
namespace lib {
|
||||
namespace iter_explorer {
|
||||
|
||||
template<class SRC, class RES, uint grp>
|
||||
class Groupy
|
||||
: public SRC
|
||||
{
|
||||
static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
|
||||
|
||||
protected:
|
||||
using Group = std::array<RES, grp>;
|
||||
using Iter = typename Group::iterator;
|
||||
union Buffer
|
||||
{
|
||||
char storage[sizeof(Group)];
|
||||
Group group;
|
||||
|
||||
Iter begin() { return group.begin();}
|
||||
Iter end() { return group.end(); }
|
||||
};
|
||||
Buffer buff_;
|
||||
uint pos_{0};
|
||||
|
||||
|
||||
public:
|
||||
using value_type = Group;
|
||||
using reference = Group&;
|
||||
using pointer = Group*;
|
||||
|
||||
Groupy() =default;
|
||||
// inherited default copy operations
|
||||
|
||||
Groupy (SRC&& dataSrc)
|
||||
: SRC{move (dataSrc)}
|
||||
{
|
||||
pullGroup(); // initially pull to establish the invariant
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over the Elements in the current group.
|
||||
* @return a Lumiera Forward Iterator with value type RES
|
||||
*/
|
||||
auto
|
||||
getGroupedElms()
|
||||
{
|
||||
ENSURE (buff_.begin()+pos_ <= buff_.end());
|
||||
// Array iterators are actually pointers
|
||||
return RangeIter{buff_.begin(), buff_.begin()+pos_};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the tail elements produced by the source,
|
||||
* which did not suffice to fill a full group.
|
||||
* @remark getRest() is NIL during regular iteration, but
|
||||
* possibly yields elements when checkPoint() = false;
|
||||
*/
|
||||
auto
|
||||
getRestElms()
|
||||
{
|
||||
return checkPoint()? RangeIter<Iter>()
|
||||
: getGroupedElms();
|
||||
}
|
||||
|
||||
/** refresh state when other layers manipulate the source sequence.
|
||||
* @note possibly pulls to re-establish the invariant */
|
||||
void
|
||||
expandChildren()
|
||||
{
|
||||
SRC::expandChildren();
|
||||
pullGroup();
|
||||
}
|
||||
|
||||
public: /* === Iteration control API for IterableDecorator === */
|
||||
|
||||
bool
|
||||
checkPoint() const
|
||||
{
|
||||
return pos_ == grp;
|
||||
}
|
||||
|
||||
reference
|
||||
yield() const
|
||||
{
|
||||
return unConst(buff_).group;
|
||||
}
|
||||
|
||||
void
|
||||
iterNext()
|
||||
{
|
||||
pullGroup();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
SRC&
|
||||
srcIter() const
|
||||
{
|
||||
return unConst(*this);
|
||||
}
|
||||
|
||||
/** @note establishes the invariant:
|
||||
* source has been consumed to fill a group */
|
||||
void
|
||||
pullGroup ()
|
||||
{
|
||||
for (pos_=0
|
||||
; pos_<grp and srcIter()
|
||||
; ++pos_,++srcIter()
|
||||
)
|
||||
buff_.group[pos_] = *srcIter();
|
||||
}
|
||||
};
|
||||
|
||||
template<uint grp, class IT>
|
||||
auto
|
||||
groupy (IT&& src)
|
||||
{
|
||||
using Value = typename meta::ValueTypeBinding<IT>::value_type;
|
||||
using ResCore = Groupy<IT, Value, grp>;
|
||||
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
|
||||
|
||||
return IterExplorer<ResIter> (ResCore {move(src)});
|
||||
}
|
||||
|
||||
}//iter_explorer
|
||||
}//lib
|
||||
|
||||
using lib::test::getTestSeq_int;
|
||||
using lib::test::VecI;
|
||||
|
||||
/** Diagnostic helper: join all the elements from a _copy_ of the iterator */
|
||||
template<class II>
|
||||
inline string
|
||||
materialise (II&& ii)
|
||||
{
|
||||
return util::join (std::forward<II> (ii), "-");
|
||||
}
|
||||
|
||||
template<uint num, uint grp>
|
||||
void
|
||||
test()
|
||||
template<class X>
|
||||
inline const void*
|
||||
getAd (X& x)
|
||||
{
|
||||
VecI vec1 = getTestSeq_int<VecI> (num);
|
||||
cout <<"---"<<grp<<" of "<<num<<"---\n"
|
||||
<< materialise(vec1) <<endl;
|
||||
|
||||
auto it = lib::explore(vec1);
|
||||
auto groupie = lib::explore(lib::iter_explorer::groupy<grp> (move(it)))
|
||||
.transform([](auto it){ return "["+util::join(*it)+"]"; });
|
||||
|
||||
for ( ;groupie; ++groupie)
|
||||
cout << *groupie<<"-";
|
||||
|
||||
CHECK (not groupie);
|
||||
CHECK (groupie.getGroupedElms());
|
||||
CHECK (groupie.getRestElms());
|
||||
for (auto r = groupie.getRestElms() ;r; ++r)
|
||||
cout << *r<<"+";
|
||||
cout << endl;
|
||||
return static_cast<const void*> (std::addressof(x));
|
||||
}
|
||||
template<class X>
|
||||
inline const void*
|
||||
getAd (X* x)
|
||||
{
|
||||
return static_cast<const void*> (x);
|
||||
}
|
||||
|
||||
template<class A, class B>
|
||||
inline bool
|
||||
isSameOb (A const& a, B const& b)
|
||||
{
|
||||
return getAd(a)
|
||||
== getAd(b);
|
||||
}
|
||||
|
||||
|
||||
struct Boo
|
||||
{
|
||||
string moo;
|
||||
short goo;
|
||||
|
||||
Boo(short uh)
|
||||
: moo{util::toString(uh-1)}
|
||||
, goo(uh+1)
|
||||
{ }
|
||||
|
||||
operator string() const
|
||||
{
|
||||
return moo+util::toString(goo);
|
||||
}
|
||||
};
|
||||
|
||||
struct SuBoo : Boo
|
||||
{
|
||||
long poo = rani(goo);
|
||||
|
||||
using Boo::Boo;
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline Boo*
|
||||
asBoo (void* mem)
|
||||
{// type tag to mark memory address as Buffer
|
||||
return static_cast<Boo*> (mem);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int, char**)
|
||||
{
|
||||
test<10,3>();
|
||||
test<13,5>();
|
||||
test<55,23>();
|
||||
test<23,55>();
|
||||
Boo boo(23);
|
||||
Boo booo(23);
|
||||
Boo* boop = &boo;
|
||||
Boo const* const beep = boop;
|
||||
cout << boo << endl;
|
||||
SHOW_EXPR(util::showAdr(getAd(boo )))
|
||||
SHOW_EXPR(util::showAdr(getAd(&boo)))
|
||||
SHOW_EXPR(util::showAdr(getAd(boop)))
|
||||
SHOW_EXPR(util::showAdr(getAd(beep)))
|
||||
SHOW_EXPR(isSameOb(boop, beep))
|
||||
SHOW_EXPR(isSameOb(&boop, &beep))
|
||||
SHOW_EXPR(isSameOb(boo, beep))
|
||||
SHOW_EXPR(isSameOb(*beep, booo))
|
||||
SHOW_EXPR(isSameOb(boo, boo.moo))
|
||||
SHOW_EXPR(isSameOb(boo, &boo.moo))
|
||||
SHOW_EXPR(isSameOb(boo.moo, booo))
|
||||
SHOW_EXPR(isSameOb(booo, asBoo(&booo.moo)))
|
||||
SHOW_EXPR(isSameOb(booo, asBoo(&booo.goo)))
|
||||
|
||||
const void* voo = boop;
|
||||
SHOW_EXPR(isSameOb(voo, boo))
|
||||
SHOW_EXPR(isSameOb(voo, boop))
|
||||
SHOW_EXPR(isSameOb(voo, asBoo(&boo.moo)))
|
||||
SHOW_EXPR(isSameOb(voo, asBoo(&booo.moo)))
|
||||
SHOW_EXPR(isSameOb(voo, asBoo(&boo.goo)))
|
||||
|
||||
Boo&& roo = move(boo);
|
||||
SHOW_EXPR(isSameOb(roo, boo))
|
||||
SHOW_EXPR(isSameOb(voo, roo))
|
||||
SHOW_EXPR(isSameOb(voo, Boo{roo}))
|
||||
|
||||
SuBoo* suBoo = static_cast<SuBoo*>(&boo);
|
||||
SHOW_EXPR(isSameOb(boo, suBoo))
|
||||
SHOW_EXPR(isSameOb(boo, suBoo->moo))
|
||||
SHOW_EXPR(isSameOb(voo, suBoo->moo))
|
||||
SHOW_EXPR(isSameOb(voo, suBoo->poo))
|
||||
|
||||
SuBoo sudo{*suBoo};
|
||||
SHOW_EXPR(isSameOb(sudo, suBoo))
|
||||
suBoo = &sudo;
|
||||
SHOW_EXPR(isSameOb(sudo.poo, suBoo->poo))
|
||||
|
||||
cout << "\n.gulp.\n";
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -271,10 +271,10 @@ namespace advice {
|
|||
Provision&
|
||||
operator= (Provision const& o)
|
||||
{
|
||||
if (!isSameObject(*this, o))
|
||||
if (not isSameObject (*this, o))
|
||||
{
|
||||
AdviceLink::operator= (o);
|
||||
setSolution ( NULL );
|
||||
setSolution (nullptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,8 +70,6 @@
|
|||
|
||||
namespace lib {
|
||||
|
||||
using util::isSameObject;
|
||||
|
||||
/**
|
||||
* Registry for tracking object instances.
|
||||
* Custom implementation of the RefArray interface,
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ namespace std {
|
|||
operator<< (basic_ostream<_CharT, _Traits>& os, X const* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
return util::showAddr(os, ptr) << " ↗" << util::StringConv<X>::invoke (*ptr);
|
||||
return util::showAdr(os, ptr) << " ↗" << util::StringConv<X>::invoke (*ptr);
|
||||
else
|
||||
return os << "⟂ «" << lib::meta::typeStr<X>() << "»";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -384,7 +384,7 @@ namespace util {
|
|||
|
||||
/** @note show only the trailing X bytes of any address */
|
||||
ostream&
|
||||
showAddr (ostream& stream, void const* addr)
|
||||
showAdr (ostream& stream, void const* addr)
|
||||
{
|
||||
IosSavepoint save{stream};
|
||||
size_t suffix_modulus = size_t(1) << DIAGNOSTICS_ADDRESS_SUFFIX_LEN * 8;
|
||||
|
|
@ -399,10 +399,10 @@ namespace util {
|
|||
|
||||
|
||||
string
|
||||
showAddr (void const* addr) noexcept
|
||||
showAdr (void const* addr) noexcept
|
||||
try {
|
||||
ostringstream buffer;
|
||||
showAddr (buffer, addr);
|
||||
showAdr (buffer, addr);
|
||||
return buffer.str();
|
||||
}
|
||||
catch(...)
|
||||
|
|
|
|||
|
|
@ -83,16 +83,16 @@ namespace meta {
|
|||
|
||||
namespace util {
|
||||
|
||||
std::string showDouble (double) noexcept;
|
||||
std::string showFloat (float) noexcept;
|
||||
std::string showSize (size_t) noexcept;
|
||||
std::string showAddr (void const* addr) noexcept;
|
||||
std::string showDouble (double) noexcept;
|
||||
std::string showFloat (float) noexcept;
|
||||
std::string showSize (size_t) noexcept;
|
||||
std::string showAdr (void const* addr) noexcept;
|
||||
|
||||
/** preconfigured format for pretty-printing of addresses */
|
||||
std::ostream& showAddr (std::ostream&, void const* addr);
|
||||
std::ostream& showAdr (std::ostream&, void const* addr);
|
||||
|
||||
/** renders the size_t in hex, optionally only trailing bytes */
|
||||
std::string showHash (size_t hash, uint showBytes=8) noexcept;
|
||||
std::string showHash (size_t hash, uint showBytes=8) noexcept;
|
||||
|
||||
inline std::string
|
||||
showHashLSB (size_t hash) noexcept
|
||||
|
|
|
|||
|
|
@ -466,14 +466,14 @@ namespace util {
|
|||
|
||||
|
||||
/** pretty-print an address as hex-suffix */
|
||||
std::string showAddr (void const* addr) noexcept;
|
||||
std::string showAdr (void const* addr) noexcept;
|
||||
|
||||
template<typename X>
|
||||
inline lib::meta::disable_if<std::is_pointer<X>,
|
||||
std::string >
|
||||
showAddr (X& elm) noexcept
|
||||
showAdr (X& elm) noexcept
|
||||
{
|
||||
return showAddr(&elm);
|
||||
return showAdr(&elm);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -482,7 +482,7 @@ namespace util {
|
|||
inline std::string
|
||||
showPtr (X* ptr =nullptr)
|
||||
{
|
||||
return ptr? showAddr(ptr) + " ↗" + StringConv<X>::invoke(*ptr)
|
||||
return ptr? showAdr(ptr) + " ↗" + StringConv<X>::invoke(*ptr)
|
||||
: BOTTOM_INDICATOR + " «" + typeStr(ptr) + "»";
|
||||
}
|
||||
|
||||
|
|
@ -492,7 +492,7 @@ namespace util {
|
|||
{
|
||||
using TargetType = typename SP::element_type;
|
||||
|
||||
return smPtr? label+"("+showAddr(smPtr.get()) + ") ↗" + StringConv<TargetType>::invoke(*smPtr)
|
||||
return smPtr? label+"("+showAdr(smPtr.get()) + ") ↗" + StringConv<TargetType>::invoke(*smPtr)
|
||||
: BOTTOM_INDICATOR + " «" + typeStr(smPtr) + "»";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,9 +86,8 @@
|
|||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
|
||||
namespace lib {
|
||||
|
|
@ -98,6 +97,7 @@ namespace lib {
|
|||
using LERR_(WRONG_TYPE);
|
||||
|
||||
using util::isSameObject;
|
||||
using util::isSameAdr;
|
||||
using util::unConst;
|
||||
|
||||
|
||||
|
|
@ -430,7 +430,7 @@ namespace lib {
|
|||
operator= (SUB const& newContent)
|
||||
{
|
||||
if (empty()
|
||||
or not isSameObject (*buff().getBase(), newContent)
|
||||
or not isSameAdr (buff().getBase(), &newContent) // caution: BaseP may be void* and SUB might be a pointer
|
||||
)
|
||||
{
|
||||
killBuffer();
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ namespace test{
|
|||
return " :---#"
|
||||
+ util::toString (1 + sizeof...(xs))
|
||||
+ " -- Type: " + showType<XX&&>()
|
||||
+ " \tAdr" + util::showAddr (x)
|
||||
+ " \tAdr" + util::showAdr (x)
|
||||
+ "\n"
|
||||
+ showVariadicTypes (std::forward<XS>(xs)...);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ using std::make_shared;
|
|||
using std::make_pair;
|
||||
using util::contains;
|
||||
using util::joinDash;
|
||||
using util::showAddr;
|
||||
using util::showAdr;
|
||||
|
||||
|
||||
namespace lib {
|
||||
|
|
@ -221,7 +221,7 @@ namespace test{
|
|||
Location loc = newAlloc.buff.front();
|
||||
ASSERT (not contains (allocs_, loc));
|
||||
newAlloc.entryID = ++entryNr_;
|
||||
logAlloc (poolID_, "allocate", bytes, newAlloc.entryID, showAddr(loc));
|
||||
logAlloc (poolID_, "allocate", bytes, newAlloc.entryID, showAdr(loc));
|
||||
checksum_ += newAlloc.entryID * bytes;
|
||||
return allocs_.emplace (loc, move(newAlloc))
|
||||
.first->second;
|
||||
|
|
@ -236,14 +236,14 @@ namespace test{
|
|||
ASSERT (entry.buff);
|
||||
ASSERT (entry.buff.front() == loc);
|
||||
if (entry.buff.size() != bytes) // *deliberately* tolerating wrong data, but log incident to support diagnostics
|
||||
logAlarm ("SizeMismatch", bytes, "≠", entry.buff.size(), entry.entryID, showAddr(loc));
|
||||
logAlarm ("SizeMismatch", bytes, "≠", entry.buff.size(), entry.entryID, showAdr(loc));
|
||||
|
||||
logAlloc (poolID_, "deallocate", bytes, entry.entryID, bytes, showAddr(loc));
|
||||
logAlloc (poolID_, "deallocate", bytes, entry.entryID, bytes, showAdr(loc));
|
||||
checksum_ -= entry.entryID * bytes; // Note: using the given size (if wrong ⟿ checksum mismatch)
|
||||
allocs_.erase(loc);
|
||||
}
|
||||
else // deliberately no exception here (for better diagnostics)
|
||||
logAlarm ("FreeUnknown", bytes, showAddr(loc));
|
||||
logAlarm ("FreeUnknown", bytes, showAdr(loc));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ namespace time {
|
|||
SmpteTC&
|
||||
SmpteTC::operator= (SmpteTC const& o)
|
||||
{
|
||||
if (!isSameObject (*this, o))
|
||||
if (not isSameObject (*this, o))
|
||||
{
|
||||
TCode::operator= (o);
|
||||
effectiveFramerate_ = o.effectiveFramerate_;
|
||||
|
|
|
|||
|
|
@ -25,12 +25,11 @@
|
|||
** Tiny helper functions and shortcuts to be used _everywhere_
|
||||
** Consider this header to be effectively included in almost every translation unit.
|
||||
** @remark The motivation of using these helpers is conciseness and uniformity of expression.
|
||||
** There are several extensions and not-so-frequently used supplements packaged into
|
||||
** separate headers.
|
||||
** Further extensions and not-so-frequently used supplements are packaged into separate headers.
|
||||
** @warning be sure to understand the ramifications of including _anything_ here...
|
||||
** @see util-coll.hpp
|
||||
** @see util-foreach.hpp
|
||||
** @see util-quant.hpp
|
||||
** @see util-foreach.hpp
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -188,6 +187,8 @@ namespace util {
|
|||
|
||||
|
||||
|
||||
/* ======== string and containment ========= */
|
||||
|
||||
/** check if string starts with a given prefix */
|
||||
inline bool
|
||||
startsWith (string const& str, string const& prefix)
|
||||
|
|
@ -354,8 +355,12 @@ namespace util {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** shortcut to save some typing when having to define
|
||||
* const and non-const variants of member functions
|
||||
* @remark the »social contract« when using this function is
|
||||
* that the programmer has to ensure effective const correctness!
|
||||
*/
|
||||
template<class OBJ>
|
||||
inline OBJ*
|
||||
|
|
@ -372,8 +377,53 @@ namespace util {
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* ======== address and identity ========= */
|
||||
|
||||
/** extract address but strip any type info */
|
||||
template<class X>
|
||||
inline const void*
|
||||
getAdr (X& x)
|
||||
{
|
||||
return static_cast<const void*> (std::addressof(x));
|
||||
}
|
||||
template<class X>
|
||||
inline const void*
|
||||
getAdr (X* x)
|
||||
{
|
||||
return static_cast<const void*> (x);
|
||||
}
|
||||
|
||||
/** generate an unique numeric ID based on the referred entity */
|
||||
template<class X>
|
||||
inline size_t
|
||||
addrID (X const& x)
|
||||
{
|
||||
return size_t(getAdr (x));
|
||||
}
|
||||
|
||||
|
||||
/** the addressable memory »slot« — platform dependent. */
|
||||
template<typename X>
|
||||
inline size_t
|
||||
slotNr (X const& x)
|
||||
{
|
||||
return addrID(x) / sizeof(size_t);
|
||||
}
|
||||
|
||||
|
||||
/** compare plain object address identity, disregarding type.
|
||||
* @note the pointee is compared when passing pointer(s)
|
||||
*/
|
||||
template<class A, class B>
|
||||
inline bool
|
||||
isSameAdr (A const& a, B const& b)
|
||||
{
|
||||
return getAdr(a) == getAdr(b);
|
||||
}
|
||||
|
||||
/** compare plain object identity,
|
||||
* bypassing any custom comparison operators.
|
||||
* based directly on the referee's memory identities.
|
||||
*/
|
||||
template<class A, class B>
|
||||
inline bool
|
||||
|
|
@ -383,38 +433,10 @@ namespace util {
|
|||
== static_cast<const void*> (std::addressof(b));
|
||||
}
|
||||
|
||||
/** extract address but strip any type info */
|
||||
template<class X>
|
||||
inline const void*
|
||||
getAddr (X& x)
|
||||
{
|
||||
return static_cast<const void*> (std::addressof(x));
|
||||
}
|
||||
template<class X>
|
||||
inline const void*
|
||||
getAddr (X* x)
|
||||
{
|
||||
return static_cast<const void*> (x);
|
||||
}
|
||||
|
||||
/** the addressable memory »slot« — platform dependent */
|
||||
template<typename X>
|
||||
inline size_t
|
||||
slotNr (X const& x)
|
||||
{
|
||||
return reinterpret_cast<size_t> (std::addressof(x)) / sizeof(size_t);
|
||||
}
|
||||
template<typename X>
|
||||
inline size_t
|
||||
slotNr (X const* x)
|
||||
{
|
||||
return reinterpret_cast<size_t> (x) / sizeof(size_t);;
|
||||
}
|
||||
|
||||
|
||||
/** determine heuristically if two objects
|
||||
* are located „close to each other“ in memory.
|
||||
* @remark can be used to find out about heap vs. stack allocation
|
||||
* @remark can be used to find out about heap versus stack allocation
|
||||
* @warning relies on platform and implementation-defined observable behaviour
|
||||
*/
|
||||
template<typename A, typename B>
|
||||
inline bool
|
||||
|
|
@ -483,6 +505,7 @@ namespace util {
|
|||
|
||||
|
||||
|
||||
|
||||
/* === some common macro definitions === */
|
||||
|
||||
/** suppress "warning: unused variable" on vars, which are
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#include "steam/engine/buffer-metadata.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
using util::isSameObject;
|
||||
using util::isSameAdr;
|
||||
|
||||
namespace steam {
|
||||
namespace engine {
|
||||
|
|
@ -243,7 +243,7 @@ namespace engine {
|
|||
bool
|
||||
BufferProvider::was_created_by_this_provider (BuffDescr const& descr) const
|
||||
{
|
||||
return isSameObject (*this, *descr.provider_);
|
||||
return isSameAdr (this, descr.provider_);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ namespace engine {
|
|||
{
|
||||
diagn::Block* block4buffer = locateBlock (typeID, specifics);
|
||||
REQUIRE (block4buffer, "releasing a buffer not allocated through this provider");
|
||||
REQUIRE (util::isSameObject(storage, block4buffer->accessMemory()));
|
||||
REQUIRE (util::isSameAdr (storage, block4buffer->accessMemory()));
|
||||
block4buffer->markReleased();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,11 +66,11 @@ namespace gear {
|
|||
{
|
||||
return string{"Act("}
|
||||
+ showVerb()
|
||||
+ util::showAddr(this)
|
||||
+ util::showAdr(this)
|
||||
+ ": "
|
||||
+ showData()
|
||||
+ "; ⤵ "
|
||||
+ (next? next->showVerb()+util::showAddr(*next)
|
||||
+ (next? next->showVerb()+util::showAdr(*next)
|
||||
: util::BOTTOM_INDICATOR)
|
||||
+ ")";
|
||||
}
|
||||
|
|
@ -106,7 +106,7 @@ namespace gear {
|
|||
+ ", quality="
|
||||
+ util::toString(data_.timing.quality);
|
||||
case NOTIFY:
|
||||
return util::showAddr(data_.notification.target)
|
||||
return util::showAdr(data_.notification.target)
|
||||
+ ", timing:"
|
||||
+ util::toString(Time{data_.notification.timing});
|
||||
case GATE:
|
||||
|
|
|
|||
|
|
@ -656,12 +656,17 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
TEST "integer rounding utility" UtilFloordiv_test <<END
|
||||
TEST "collection utils" UtilCollection_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "integer scale wrapping utility" UtilFloorwrap_test <<END
|
||||
TEST "util: integer rounding" UtilFloordiv_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "util: integer scale wrapping" UtilFloorwrap_test <<END
|
||||
out-lit: --------int--------12/4
|
||||
out-lit: 12 / 4 = 3 % = 0 floor= 3.0 wrap = ( 3, 0)
|
||||
out-lit: 11 / 4 = 2 % = 3 floor= 2.0 wrap = ( 2, 3)
|
||||
|
|
@ -770,7 +775,7 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
TEST "collection utils" UtilCollection_test <<END
|
||||
TEST "util: address identity" UtilIdentity_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
|
|
|||
|
|
@ -32,12 +32,8 @@
|
|||
#include "lib/error.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
using LERR_(ASSERTION);
|
||||
using util::isSameObject;
|
||||
using util::typeStr;
|
||||
using std::rand;
|
||||
|
||||
|
||||
namespace lib {
|
||||
|
|
@ -62,7 +58,7 @@ namespace test{
|
|||
class DigxelConfigurations_test : public Test
|
||||
{
|
||||
virtual void
|
||||
run (Arg)
|
||||
run (Arg)
|
||||
{
|
||||
verifyConfiguration<Digxel<int> > (123);
|
||||
verifyConfiguration<Digxel<double>> (123.4567);
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ namespace test{
|
|||
|
||||
TestDigxel d2(d1);
|
||||
CHECK (d2 == someValue);
|
||||
CHECK (!isSameObject (d1, d2));
|
||||
CHECK (not isSameObject (d1, d2));
|
||||
|
||||
d1 = randomFrac();
|
||||
CHECK (d1 != d2);
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
using ::Test;
|
||||
using lib::explore;
|
||||
using lib::test::showSizeof;
|
||||
using util::getAddr;
|
||||
using util::getAdr;
|
||||
using util::isnil;
|
||||
|
||||
using std::numeric_limits;
|
||||
|
|
@ -306,7 +306,7 @@ namespace test {
|
|||
// trigger overflow and allocation of second extent
|
||||
char& c2 = clu.create<char> ('U');
|
||||
CHECK (blk != currBlock()); // allocation moved to a new extent
|
||||
CHECK (getAddr(c2) == currBlock() + 2*sizeof(void*)); // c2 resides immediately after the two administrative »slots«
|
||||
CHECK (getAdr(c2) == currBlock() + 2*sizeof(void*)); // c2 resides immediately after the two administrative »slots«
|
||||
CHECK (clu.storage_.rest == EXTSIZ - posOffset());
|
||||
CHECK (clu.numBytes() == EXTSIZ - 2*sizeof(void*) + 1); // accounted allocation for the full first block + one byte
|
||||
CHECK (clu.numExtents() == 2); // we have two extents now
|
||||
|
|
|
|||
|
|
@ -44,9 +44,7 @@ using ::test::Test;
|
|||
using std::array;
|
||||
|
||||
using lib::explore;
|
||||
using util::isSameObject;
|
||||
using util::isLimited;
|
||||
using util::getAddr;
|
||||
using util::isnil;
|
||||
using util::join;
|
||||
|
||||
|
|
@ -486,7 +484,7 @@ namespace test{
|
|||
void
|
||||
check_ElementStorage()
|
||||
{
|
||||
auto loc = [](auto& something){ return size_t(getAddr (something)); };
|
||||
auto loc = [](auto& something){ return util::addrID (something); };
|
||||
auto calcSpread = [&](auto& several){ return loc(several[1]) - loc(several[0]); };
|
||||
|
||||
{ // Scenario-1 : tightly packed values
|
||||
|
|
@ -532,6 +530,7 @@ namespace test{
|
|||
CHECK (5 == elms.size());
|
||||
auto moved = move(elms);
|
||||
CHECK (5 == moved.size());
|
||||
CHECK (loc(elms) != loc(moved));
|
||||
CHECK (isnil (elms));
|
||||
|
||||
CHECK (loc(moved[0]) == p0);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ namespace test {
|
|||
|
||||
using util::_Fmt;
|
||||
using util::isnil;
|
||||
using util::getAddr;
|
||||
using util::getAdr;
|
||||
using util::isSameObject;
|
||||
using std::string;
|
||||
using std::move;
|
||||
|
|
@ -509,14 +509,14 @@ namespace test {
|
|||
CHECK (s->start == -100);
|
||||
CHECK (s->after == 2);
|
||||
CHECK (s->id == id1);
|
||||
CHECK (adr1 == getAddr(*s));
|
||||
CHECK (adr1 == getAdr(*s));
|
||||
CHECK (s != p);
|
||||
++s;
|
||||
CHECK (s == p);
|
||||
CHECK (s->start == 2);
|
||||
CHECK (s->after == 3);
|
||||
CHECK (s->id == id2);
|
||||
CHECK (adr2 != getAddr(*s)); // this is the first part of the split segment (new allocation)
|
||||
CHECK (adr2 != getAdr(*s)); // this is the first part of the split segment (new allocation)
|
||||
++s;
|
||||
CHECK (s != p);
|
||||
CHECK (s == n);
|
||||
|
|
@ -525,7 +525,7 @@ namespace test {
|
|||
CHECK (s->id != id1);
|
||||
CHECK (s->id != id2);
|
||||
CHECK (s->id != id3);
|
||||
CHECK (adr2 != getAddr(*s));
|
||||
CHECK (adr2 != getAdr(*s));
|
||||
++s;
|
||||
CHECK (s != n);
|
||||
CHECK (s != a);
|
||||
|
|
@ -534,7 +534,7 @@ namespace test {
|
|||
CHECK (s->id != id1);
|
||||
CHECK (s->id == id2);
|
||||
CHECK (s->id != id3);
|
||||
CHECK (adr2 != getAddr(*s)); // this is the second part of the split segment (new allocation)
|
||||
CHECK (adr2 != getAdr(*s)); // this is the second part of the split segment (new allocation)
|
||||
++s;
|
||||
CHECK (s == a);
|
||||
CHECK (s->start == 6);
|
||||
|
|
@ -542,7 +542,7 @@ namespace test {
|
|||
CHECK (s->id != id1);
|
||||
CHECK (s->id != id2);
|
||||
CHECK (s->id == id3);
|
||||
CHECK (adr3 == getAddr(*s));
|
||||
CHECK (adr3 == getAdr(*s));
|
||||
++s;
|
||||
CHECK (s == segs.end());
|
||||
}
|
||||
|
|
|
|||
229
tests/library/util-identity-test.cpp
Normal file
229
tests/library/util-identity-test.cpp
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
UtilIdentity(Test) - helpers for identity and memory location
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2024, 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 util-identity-test.cpp
|
||||
** unit test \ref UtilIdentity_test
|
||||
*/
|
||||
|
||||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/format-obj.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
using std::move;
|
||||
using std::string;
|
||||
|
||||
|
||||
namespace util {
|
||||
namespace test {
|
||||
|
||||
|
||||
|
||||
/*****************************************************************//**
|
||||
* @test verify identity based on memory address location,
|
||||
* which can be relevant for custom allocation schemes
|
||||
* and to prevent self-assignment.
|
||||
* - access to a given entitie's address is used as foundation,
|
||||
* with the _special twist_ that a pointer is »unpacked«
|
||||
* - based on this address, an ID-number can be generated
|
||||
* - moreover, two flavours of identity check are provided
|
||||
* + util::isSameObject compares at the level of the
|
||||
* _language object_ — it takes its arguments _solely_
|
||||
* by reference and does not »unpack« a pointer.
|
||||
* The term [object] is used here as in the C++ standard
|
||||
* + util::isSameAdr accepts any mix of references and
|
||||
* pointers, disregarding any type information, thereby
|
||||
* _»unpacking«_ the address information contained in a
|
||||
* pointer is (i.e. the address of the pointee is used)
|
||||
* [object]: https://en.cppreference.com/w/cpp/language/type
|
||||
*/
|
||||
class UtilIdentity_test : public Test
|
||||
{
|
||||
|
||||
void
|
||||
run (Arg)
|
||||
{
|
||||
verify_getAdr();
|
||||
verify_addrID();
|
||||
verify_isSameAdr();
|
||||
verify_isSameObject();
|
||||
}
|
||||
|
||||
|
||||
/** @test determine the address of an referred entity,
|
||||
* possibly _unpacking_ a pointer (using its content)
|
||||
*/
|
||||
void
|
||||
verify_getAdr()
|
||||
{
|
||||
CHECK (getAdr (this) == this);
|
||||
CHECK (getAdr (*this) == this);
|
||||
|
||||
CStr aloof[2] = {"reality", "check"};
|
||||
CHECK (getAdr (aloof) == &aloof);
|
||||
CHECK (getAdr (&aloof[0]) == &aloof);
|
||||
CHECK (getAdr (&aloof[1]) == aloof+1);
|
||||
CHECK (getAdr ( aloof[0]) == aloof[0]);
|
||||
CHECK (getAdr ( aloof[1]) == aloof[1]);
|
||||
}
|
||||
|
||||
/** @test generate a numeric ID based on the memory address. */
|
||||
void
|
||||
verify_addrID()
|
||||
{
|
||||
uint ui[2] = {2,3};
|
||||
CHECK (addrID (ui[1]) == addrID (ui[0]) + sizeof(uint));
|
||||
|
||||
uint* up{ui+1};
|
||||
CHECK (addrID (ui[1]) == addrID (up));
|
||||
}
|
||||
|
||||
|
||||
/** dummy entity to compare */
|
||||
struct Boo
|
||||
{
|
||||
short moo;
|
||||
string woo;
|
||||
|
||||
Boo()
|
||||
: moo(rani(1000))
|
||||
, woo{toString(moo-1)}
|
||||
{ }
|
||||
};
|
||||
|
||||
struct SuBoo : Boo
|
||||
{
|
||||
using Boo::Boo;
|
||||
size_t poo{addrID (this)};
|
||||
};
|
||||
|
||||
static Boo* asBoo (void* mem) { return static_cast<Boo*> (mem); }
|
||||
|
||||
|
||||
/** @test determine identity of referred arguments based on their
|
||||
* memory location; pointers are unpacked, referring to the pointee.
|
||||
*/
|
||||
void
|
||||
verify_isSameAdr()
|
||||
{
|
||||
Boo boo;
|
||||
Boo booo;
|
||||
Boo* boop = &boo;
|
||||
Boo const* const beep = boop;
|
||||
CHECK (boo.moo != booo.moo);
|
||||
CHECK (boo.moo == boop->moo);
|
||||
CHECK ( isSameAdr (boop, beep));
|
||||
CHECK (not isSameAdr (&boop,&beep));
|
||||
CHECK ( isSameAdr (boo, beep));
|
||||
CHECK ( isSameAdr (*beep, boo ));
|
||||
CHECK (not isSameAdr (*beep, booo));
|
||||
CHECK ( isSameAdr (boo, boo.moo));
|
||||
CHECK ( isSameAdr (boo, &boo.moo));
|
||||
CHECK (not isSameAdr (boo.moo, booo));
|
||||
CHECK ( isSameAdr (booo, asBoo(&booo.moo)));
|
||||
CHECK (not isSameAdr (booo, asBoo(&booo.woo)));
|
||||
|
||||
// handles also void*
|
||||
const void* voo = boop;
|
||||
CHECK ( isSameAdr (voo, boo));
|
||||
CHECK ( isSameAdr (voo, boop));
|
||||
CHECK (not isSameAdr (voo, booo));
|
||||
CHECK ( isSameAdr (voo, asBoo(&boo.moo)));
|
||||
CHECK (not isSameAdr (voo, asBoo(&booo.moo)));
|
||||
CHECK (not isSameAdr (voo, asBoo(&boo.woo)));
|
||||
|
||||
// RValue taken by ref
|
||||
Boo&& roo = move(boo);
|
||||
CHECK ( isSameAdr (roo, boo));
|
||||
CHECK ( isSameAdr (voo, roo));
|
||||
CHECK (not isSameAdr (voo, Boo{roo}));
|
||||
|
||||
// type information disregarded
|
||||
SuBoo* suBoo = static_cast<SuBoo*>(&boo);
|
||||
CHECK ( isSameAdr (boo, suBoo));
|
||||
CHECK ( isSameAdr (boo, suBoo->moo));
|
||||
CHECK ( isSameAdr (voo, suBoo->moo));
|
||||
CHECK (not isSameAdr (voo, suBoo->poo));
|
||||
|
||||
SuBoo sudo{*suBoo};
|
||||
CHECK (not isSameAdr (sudo, boo));
|
||||
CHECK (not isSameAdr (sudo, suBoo));
|
||||
suBoo = &sudo;
|
||||
CHECK ( isSameAdr (sudo.poo, suBoo->poo));
|
||||
}
|
||||
|
||||
/** @test determine strictly the identity of referred entities as given. */
|
||||
void
|
||||
verify_isSameObject()
|
||||
{
|
||||
Boo boo;
|
||||
Boo booo;
|
||||
Boo* boop = &boo;
|
||||
Boo* woop = boop;
|
||||
Boo& foop = *woop;
|
||||
CHECK ( isSameObject (boo, boo ));
|
||||
CHECK ( isSameObject (booo, booo));
|
||||
CHECK (not isSameObject (boo, booo));
|
||||
CHECK (not isSameObject (booo, boo ));
|
||||
// pointers count as »objects« and are not dereferenced
|
||||
CHECK (not isSameObject (boop, woop));
|
||||
CHECK (not isSameObject (boop, booo));
|
||||
CHECK (not isSameObject (boop, boo ));
|
||||
CHECK (not isSameObject (booo, woop));
|
||||
CHECK (not isSameObject (boo , woop));
|
||||
CHECK ( isSameObject (boo , foop));
|
||||
CHECK ( isSameObject (foop, boo ));
|
||||
CHECK (not isSameObject (foop, boop));
|
||||
CHECK (not isSameObject (foop, woop));
|
||||
CHECK (not isSameObject (foop, &boo ));
|
||||
CHECK ( isSameObject (foop, *boop));
|
||||
CHECK ( isSameObject (*boop, foop));
|
||||
|
||||
// RValue taken by ref
|
||||
Boo&& roo = move(boo);
|
||||
CHECK ( isSameObject (roo, boo));
|
||||
CHECK (not isSameObject (boo, Boo{roo}));
|
||||
|
||||
// type information disregarded
|
||||
SuBoo* suBoo = static_cast<SuBoo*>(&boo);
|
||||
CHECK ( isSameObject (boo, *suBoo));
|
||||
CHECK ( isSameObject (boo, suBoo->moo));
|
||||
CHECK (not isSameObject (boo, suBoo->woo));
|
||||
|
||||
// void* is treated as a distinct object
|
||||
void* voo = boop;
|
||||
CHECK (not isSameObject (voo , boop));
|
||||
CHECK (not isSameObject (voo , boo));
|
||||
CHECK (not isSameObject (voo , &boo)); // ...not getting anywhere...
|
||||
CHECK (not isSameObject (voo , asBoo(&boo)));
|
||||
CHECK (not isSameObject (boo , asBoo(&boo)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
LAUNCHER (UtilIdentity_test, "unit common");
|
||||
|
||||
}} // namespace util::test
|
||||
|
||||
|
|
@ -41,9 +41,8 @@ using std::tuple_size_v;
|
|||
namespace util {
|
||||
namespace test {
|
||||
|
||||
typedef std::vector<uint> VecI;
|
||||
typedef lib::RangeIter<VecI::iterator> RangeI;
|
||||
|
||||
using VecI = std::vector<uint>;
|
||||
using RangeI = lib::RangeIter<VecI::iterator>;
|
||||
|
||||
|
||||
namespace{ // Test data and operations
|
||||
|
|
|
|||
|
|
@ -555,7 +555,7 @@ namespace test {
|
|||
buildActivationTap (Activity const& subject, string id ="")
|
||||
{
|
||||
return mockActs_.emplace_back (subject
|
||||
,isnil(id)? "tap-"+subject.showVerb()+util::showAddr(subject)
|
||||
,isnil(id)? "tap-"+subject.showVerb()+util::showAdr(subject)
|
||||
: id
|
||||
,eventLog_
|
||||
,invocationSeq_);
|
||||
|
|
@ -566,14 +566,14 @@ namespace test {
|
|||
insertActivationTap (Activity*& wiring, string id ="")
|
||||
{
|
||||
wiring = wiring? & buildActivationTap (*wiring, id)
|
||||
: & buildActivationProbe (isnil(id)? "tail-"+util::showAddr(&wiring) : id);
|
||||
: & buildActivationProbe (isnil(id)? "tail-"+util::showAdr(&wiring) : id);
|
||||
return *wiring;
|
||||
}
|
||||
|
||||
Activity&
|
||||
buildGateWatcher (Activity& gate, string id ="")
|
||||
{
|
||||
insertActivationTap (gate.next, "after-" + (isnil(id)? gate.showVerb()+util::showAddr(gate) : id));
|
||||
insertActivationTap (gate.next, "after-" + (isnil(id)? gate.showVerb()+util::showAdr(gate) : id));
|
||||
return buildActivationTap (gate, id);
|
||||
}
|
||||
|
||||
|
|
@ -581,7 +581,7 @@ namespace test {
|
|||
watchGate (Activity*& wiring, string id ="")
|
||||
{
|
||||
wiring = wiring? & buildGateWatcher (*wiring, id)
|
||||
: & buildActivationProbe (isnil(id)? "tail-"+util::showAddr(&wiring) : id);
|
||||
: & buildActivationProbe (isnil(id)? "tail-"+util::showAdr(&wiring) : id);
|
||||
return *wiring;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1623,7 +1623,7 @@ namespace test {
|
|||
{
|
||||
return _Fmt{"ChainCalc(w:%d)◀%s"}
|
||||
% maxFan
|
||||
% util::showAddr(startNode_);
|
||||
% util::showAdr(startNode_);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -16189,9 +16189,7 @@
|
|||
</node>
|
||||
<node CREATED="1523232888115" ID="ID_800807629" MODIFIED="1523232908023">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
aber genau das ist hier jeweils nur <i>in einem Fall</i> gegeben
|
||||
|
|
@ -17093,9 +17091,7 @@
|
|||
</node>
|
||||
<node CREATED="1504193354056" FOLDED="true" ID="ID_385011645" MODIFIED="1518487921077">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<b>Abstraktion</b> zur Steuerung schaffen
|
||||
|
|
@ -17569,9 +17565,7 @@
|
|||
<node CREATED="1541088360999" ID="ID_1860524548" MODIFIED="1557498707223" TEXT="horizontale Ausdehnung steuerbar">
|
||||
<node CREATED="1541088395516" ID="ID_122658669" MODIFIED="1576282358102" TEXT="natürlich">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
d.h. das Widget unternimmt selber nichts, und überläßt GTK die Größenbestimmung
|
||||
|
|
@ -18101,9 +18095,7 @@
|
|||
<node CREATED="1654448154480" ID="ID_1428501909" MODIFIED="1654448287941" TEXT="LABEL">
|
||||
<node CREATED="1654448495868" ID="ID_278262506" MODIFIED="1662037668001" TEXT="oder MARKER?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Terminologie nicht klar...
|
||||
|
|
@ -19118,9 +19110,7 @@
|
|||
</node>
|
||||
<node CREATED="1664767140485" ID="ID_428399436" MODIFIED="1664767217656" TEXT="vor allem die wieder-einblenden-Sequenz ist gefährlich">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...denn sie wird für jeden Fokuswechsel und für jeden erfolglosen Versuch erneut durchlaufen, und zwar in den meisten Fällen (Label) bis zum 3.Schritt, nur um dann zu merken, daß eben doch nichts mehr rauszuholen ist.
|
||||
|
|
@ -20180,9 +20170,7 @@
|
|||
<node CREATED="1666285046869" ID="ID_925433658" MODIFIED="1666285057773" TEXT="setzt dann Zeiten und Namen"/>
|
||||
<node CREATED="1666285058499" ID="ID_1175866676" MODIFIED="1666285084060">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
und danach feuert der <i>StructuralChange</i>-Listener
|
||||
|
|
@ -22387,9 +22375,7 @@
|
|||
</node>
|
||||
<node COLOR="#338800" CREATED="1575845743838" ID="ID_1827383151" MODIFIED="1582503290754" TEXT="testContainsSequence()-predicate does not work properly in the initial base check">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
again the problem with the reversed order due to forward_list
|
||||
|
|
@ -46584,9 +46570,7 @@
|
|||
</node>
|
||||
<node CREATED="1448078798369" ID="ID_819750758" MODIFIED="1576282358014" TEXT="komplett-Reset">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
mark "reset"
|
||||
|
|
@ -46811,9 +46795,7 @@
|
|||
<node CREATED="1455236382183" ID="ID_983670310" MODIFIED="1518487921086" TEXT="Einstiegspunkt: revealYourself"/>
|
||||
<node CREATED="1455236393861" ID="ID_1638665625" MODIFIED="1518487921086">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
support ist <i>optional</i>
|
||||
|
|
@ -47175,9 +47157,7 @@
|
|||
</body>
|
||||
</html></richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
das mag überraschen --
|
||||
|
|
@ -47476,9 +47456,7 @@
|
|||
<node CREATED="1455913759727" HGAP="43" ID="ID_1318158783" MODIFIED="1512926191911" TEXT="Modell">
|
||||
<node CREATED="1455913778429" ID="ID_884750408" MODIFIED="1575133325713" TEXT="sub-Collections">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
eindeutig überlegen
|
||||
|
|
@ -56354,6 +56332,29 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1731602067582" ID="ID_1120424143" MODIFIED="1731602071322" TEXT="Ausdrucksmittel">
|
||||
<node CREATED="1731602123520" ID="ID_614194653" MODIFIED="1731602280844" TEXT="Speicher-Identität">
|
||||
<linktarget COLOR="#59586c" DESTINATION="ID_614194653" ENDARROW="Default" ENDINCLINATION="-1423;212;" ID="Arrow_ID_1656634027" SOURCE="ID_180344920" STARTARROW="None" STARTINCLINATION="-701;37;"/>
|
||||
<node CREATED="1731600837017" ID="ID_1200940596" MODIFIED="1731600906446" TEXT="isSameObject">
|
||||
<font NAME="Monospaced" SIZE="12"/>
|
||||
<node CREATED="1731600933000" ID="ID_562384209" MODIFIED="1731600960815" TEXT="nimmt die Argumente stets als Referenz"/>
|
||||
<node CREATED="1731600962593" ID="ID_1995003068" MODIFIED="1731600989770" TEXT="vergleicht die Speicher-Idenität der referierten Objekte"/>
|
||||
<node CREATED="1731600990479" ID="ID_1074322955" MODIFIED="1731601028461" TEXT="Pointer sind "objects" im Sinne von C++ ⟹ es werden nicht die Pointees verglichen"/>
|
||||
<node CREATED="1731601031372" ID="ID_1290492988" MODIFIED="1731601052890" TEXT="das heißt, dies ist die bestehende Funktion, und sie bleibt so, wie sie ist"/>
|
||||
</node>
|
||||
<node CREATED="1731600845818" ID="ID_570811457" MODIFIED="1731600923731" TEXT="isSameAddr">
|
||||
<font NAME="Monospaced" SIZE="12"/>
|
||||
<node CREATED="1731601069781" ID="ID_1090427138" MODIFIED="1731601080522" TEXT="nimmt einen beliebigen Mix von Pointern oder Referenzen"/>
|
||||
<node CREATED="1731601081698" ID="ID_925316830" MODIFIED="1731601099164" TEXT="Pointer werden selber als Referenz gedeutet und einmal dereferenziert"/>
|
||||
<node CREATED="1731601100055" ID="ID_957797383" MODIFIED="1731601116708" TEXT="die dadurch bezeichneten "objects" werden verglichen"/>
|
||||
<node CREATED="1731601117550" ID="ID_83648196" MODIFIED="1731601164748" TEXT="das heißt, dies ist die neue flexible Implementierung (für spezielle Fälle)"/>
|
||||
<node CREATED="1731601170863" ID="ID_88090345" MODIFIED="1731601192896" TEXT="im Besonderen können wir damit void* vergleichen (was bisher unmöglich war)"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#c8c0b6" CREATED="1731602329563" HGAP="12" ID="ID_35905059" MODIFIED="1731624715759" TEXT="util-identity-test.cpp" VSHIFT="12">
|
||||
<icon BUILTIN="forward"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1573230375839" ID="ID_270568302" MODIFIED="1573230382276" TEXT="policies">
|
||||
<node CREATED="1573230393523" ID="ID_1929317164" MODIFIED="1573230398694" TEXT="wie viel const-correctness?">
|
||||
|
|
@ -57524,9 +57525,7 @@
|
|||
</html></richcontent>
|
||||
<node CREATED="1731516823812" ID="ID_1419872560" MODIFIED="1731516925668" TEXT="bedingt durch Reorganisation #includes">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...hatte vor einiger Zeit aufgeräumt und einen eigenen #include "lib/integral.hpp" geschaffen. Dadurch ist downstream der #include für time-value.hpp rausgefallen, und damit fehlte die String-conversion für Rationals
|
||||
|
|
@ -57537,9 +57536,7 @@
|
|||
</node>
|
||||
<node CREATED="1731516926921" ID="ID_1885341686" MODIFIED="1731516970756" TEXT="die eigentliche Ursache ist das ungelöste Problem mit FSecs">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...dazu nochmal über die ganze Problematik nachgedacht und entsprechende Kommentare in #1258 und #1261 hinterlassen
|
||||
|
|
@ -57589,11 +57586,21 @@
|
|||
<font size="1">END </font>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1731624499756" ID="ID_293265001" MODIFIED="1731624683932" TEXT="WorkForce_test">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">CHECK: work-force-test.cpp:425: thread_1: verify_scalePool: (2*fullCnt == uniqueCnt) </font>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1731467207226" ID="ID_977237610" MODIFIED="1731467207226" TEXT="TrackingHeapBlockProvider_test">
|
||||
<node CREATED="1731467220749" ID="ID_1574698883" MODIFIED="1731467357686" TEXT="ASSERTION">
|
||||
<node COLOR="#435e98" CREATED="1731467207226" ID="ID_977237610" MODIFIED="1731624884569" TEXT="TrackingHeapBlockProvider_test">
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1731467220749" ID="ID_1574698883" MODIFIED="1731624803495" TEXT="ASSERTION">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
|
|
@ -57601,16 +57608,245 @@
|
|||
0000000516: PRECONDITION: tracking-heap-block-provider.cpp:281: thread_1: detachBuffer: (util::isSameObject(storage, block4buffer->accessMemory()))
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<linktarget COLOR="#73384b" DESTINATION="ID_1574698883" ENDARROW="Default" ENDINCLINATION="-9;41;" ID="Arrow_ID_986253090" SOURCE="ID_844778131" STARTARROW="None" STARTINCLINATION="30;3;"/>
|
||||
<linktarget COLOR="#73384b" DESTINATION="ID_1574698883" ENDARROW="Default" ENDINCLINATION="-9;41;" ID="Arrow_ID_1250752825" SOURCE="ID_74232375" STARTARROW="None" STARTINCLINATION="34;4;"/>
|
||||
<node CREATED="1731518054338" ID="ID_1029594237" MODIFIED="1731519199214" TEXT="neu eingeführt im Juli 2024 — wegen LocalTag">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Damals im Juli habe ich versucht, die Info zum Ausgabe-Buffer durch das allgemeine Buffer-Handling-Framework durchzufädeln; dafür habe ich das <font color="#0b0d8d" face="Monospaced">LocalTag</font> (vorher <font color="#0b0d8d" face="Monospaced">LocalKey</font> genannt) eingesetzt; in der weiteren Entwicklung habe ich jedoch dann diesen architektonisch unpassenden Ansatz verworfen und die Identifikation des Ausgabe-Buffers direkt in den Aufruf von oben hereingegeben.
|
||||
</p>
|
||||
<p>
|
||||
In diesem Zusammenhang habe ich das BufferProvider-Framework nochmal genauer angeschaut, einige potentielle Gefahren abgedichtet und — TADAA — <b>zusätzliche Assertions</b> eingebaut, die jetzt ansprechen. Gut gebrüllt, Löwe
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1731518770635" ID="ID_1551802265" MODIFIED="1731519196383">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
ich hab damals auf <i>theoretischem Weg</i> die Gefahr duplikater Einträge entdeckt...
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Und zwar durch den Umstand, daß die Einträge im Buffer-Provider durch Key-Records markiert sind, welche untereinander hierarchisch zusammenhängen können. Denn zunächst stellt ein solcher Eintrag einen Buffer-Typ dar, von dem dann viele einzelne konkrete Buffer registiert und verwarbeitet werden. Das Problem entsteht nun aber, weil auch ein zusätzliches LocalTag mit in den Key einfließt zur zusätzlichen Differenzierung. Das ist zunächst sinnvoll, um einen Typ zusätzlich zu qualifizieren. Gefährlich ist aber, daß zu einem bestehenden Buffer mit Adresse noch ein Local-Tag hinzugefügt werden könnte, oder daß man versucht, die gleiche Adresse einmal mit und einmal ohne LocalTag anzusprechen. Denn dadurch würden zwei Metadatensätze erzeugt, die dann jeweils auch einen eigenständigen Lifecycle durchlaufen, obwohl sie zur gleichen Buffer-Adresse gehören.
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1731519381164" ID="ID_768637407" MODIFIED="1731519497995" TEXT="mir war aufgefallen, daß für release() eines Buffers die Adress-Info auf zwei Wegen vorliegt">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...und aber eine dieser Infos einfach ignoriert wird, nämlich die konkrete Info, die der im BuffHandle vom Client eingebettet ist. Daher habe ich für die einzige Implementierung, den TrackingHeapBlockProvider beide Infos in einer Assertion verglichen. Und genau dieser Check scheitert jetzt (noch nicht klar warum)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1731519941439" ID="ID_357574011" MODIFIED="1731519948226" TEXT="Untersuchung...">
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1731519949320" ID="ID_240715659" MODIFIED="1731519987357" TEXT="Call-Path: simpleExample() ⟶ provider.releaseBuffer(testBuff)"/>
|
||||
<node CREATED="1731520006047" ID="ID_577977745" MODIFIED="1731520016425" TEXT="Debugger">
|
||||
<node CREATED="1731529842821" ID="ID_304693119" MODIFIED="1731529854030" TEXT="nebenbei bemerkt: TypeHandler verwendet eine identity">
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1731529855307" ID="ID_1862852828" MODIFIED="1731529863928" TEXT="wozu wird die verwendet?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1731529995641" ID="ID_570070738" MODIFIED="1731530005496" TEXT="Aua: für hash_value">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
<node CREATED="1731530923708" ID="ID_1704286619" MODIFIED="1731530935278" TEXT="Problem bestätigt: fließt in die Key-Identity ein"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1731529864690" ID="ID_1980255586" MODIFIED="1731529881765" TEXT="die baut nur auf dem Typ der Funktoren auf">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1731529882792" ID="ID_206400237" MODIFIED="1731529889643" TEXT="das ist rein-logisch zu wenig"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1731529890448" ID="ID_1813009572" MODIFIED="1731529914846" TEXT="wir bräuchten einen Hash des konkreten Funktors">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1731467215176" ID="ID_844778131" MODIFIED="1731467314156" TEXT="BufferProviderProtocol_test">
|
||||
</node>
|
||||
<node CREATED="1731530752729" ID="ID_1739111078" MODIFIED="1731530782462" TEXT="außerdem: TypeHandler wird x-fach als Argument kopiert">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
und zwar für die Key-Erstellung; die nimmt wohl das Argument by-value
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1731532150744" FOLDED="true" ID="ID_1436652987" MODIFIED="1731624876192" TEXT="eigentlicher Fehler ist »trivial«">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1731532165222" ID="ID_1833321928" MODIFIED="1731624871572" TEXT="util::isSameObject() funktioniert nicht mit Pointern">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
<node CREATED="1731532197465" ID="ID_1421822856" MODIFIED="1731532204220" TEXT="das Problem hatte ich schon mehrfach....">
|
||||
<node CREATED="1731532205120" ID="ID_1252046258" MODIFIED="1731532213103" TEXT="da wird dann der Overload für Referenzen genommen"/>
|
||||
<node CREATED="1731532213703" ID="ID_502132953" MODIFIED="1731532231897" TEXT="und dann bekommt man die Adresse des Pointers, nicht das Pointee"/>
|
||||
</node>
|
||||
<node CREATED="1731557607155" ID="ID_369696513" MODIFIED="1731557634957" TEXT="ist hier besonders lästig, weil eine Seite als void* reinkommt"/>
|
||||
<node COLOR="#338800" CREATED="1731557638735" ID="ID_84382244" MODIFIED="1731624765483" TEXT="kann man diese Funktion vielleicht doch generischer implementieren?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1731557658612" ID="ID_883821710" MODIFIED="1731557746261" TEXT="Untersuchung in separater translation-unit (try.cpp)">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
bisher hab ich immer den »Fehler« gemacht, solche trickreichen Experimente im Blindflug in util.hpp machen zu wollen. Das ging dann schief, und nach drei vergeblichen Versuchen hab ich das Thema aufgegeben, schließlich dauert jeder Build 5 Minuten.....
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1731557747600" ID="ID_853752206" MODIFIED="1731607866837" TEXT="was ist eigentlich das Problem...??">
|
||||
<node CREATED="1731557774684" ID="ID_1079471653" MODIFIED="1731557781559" TEXT="man kann auf getAddr() aufbauen"/>
|
||||
<node CREATED="1731557782127" ID="ID_923836116" MODIFIED="1731557807312">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
es braucht hier <b>kein</b> perfect-forwarding
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<font NAME="SansSerif" SIZE="12"/>
|
||||
</node>
|
||||
<node CREATED="1731557814482" ID="ID_1814674606" MODIFIED="1731557862676" TEXT="und Overload-Resolution trennt const* problemlos von const&"/>
|
||||
<node CREATED="1731557865776" ID="ID_1157127706" MODIFIED="1731557879306" TEXT="gleich noch x-fach verschiedene Aufruf-Varianten erprobt"/>
|
||||
<node CREATED="1731557880370" ID="ID_1944561028" MODIFIED="1731607927621" TEXT="gibt es dann nicht doch irgend welche ekelhaften Grenzfälle...?">
|
||||
<arrowlink COLOR="#fef1a9" DESTINATION="ID_571510979" ENDARROW="Default" ENDINCLINATION="1;-21;" ID="Arrow_ID_441150383" STARTARROW="None" STARTINCLINATION="-165;7;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1731557904987" ID="ID_1391232069" MODIFIED="1731607858554" TEXT="also mal versuchsweise tatsächlich umgestellt">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e9e37f" COLOR="#d70657" CREATED="1731557924088" ID="ID_571510979" MODIFIED="1731607954840" TEXT="ein paar Tests scheitern">
|
||||
<linktarget COLOR="#fef1a9" DESTINATION="ID_571510979" ENDARROW="Default" ENDINCLINATION="1;-21;" ID="Arrow_ID_441150383" SOURCE="ID_1944561028" STARTARROW="None" STARTINCLINATION="-165;7;"/>
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1731557952732" ID="ID_777170043" MODIFIED="1731557953581" TEXT="ReplaceableItem_test">
|
||||
<node CREATED="1731558129469" ID="ID_1886714615" MODIFIED="1731558148849" STYLE="bubble">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<font face="Monospaced">CHECK ( isSameObject (*ptrWrap.get(), x)); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced">CHECK (!isSameObject ( ptrWrap.get(), x));</font>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1731558151929" ID="ID_610281553" MODIFIED="1731558167499" TEXT="tja ... das geht jetzt nicht mehr mit der »verbesserten« Funktion"/>
|
||||
</node>
|
||||
<node CREATED="1731557965170" ID="ID_878035767" MODIFIED="1731557966708" TEXT="Symbol_test">
|
||||
<node CREATED="1731558015153" ID="ID_1322838504" MODIFIED="1731558560689" STYLE="bubble">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<font face="Monospaced">CHECK (not isSameObject (y1.c(), y2.c()));  </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced">CHECK (    isSameObject (*y1.c(), *y2.c()));</font>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1731558175623" ID="ID_1288225438" MODIFIED="1731558197241" TEXT="gleiches Problem hier: jetzt werden die Pointees verglichen, und die sind tatsächlich gleich"/>
|
||||
</node>
|
||||
<node CREATED="1731557941189" ID="ID_1041472032" MODIFIED="1731559882555" TEXT="ItemWrapper_test">
|
||||
<node CREATED="1731557968137" ID="ID_1008712171" MODIFIED="1731557978948" TEXT="hier entgleist die self-Assignment-Sperre"/>
|
||||
<node CREATED="1731559053809" ID="ID_459077352" MODIFIED="1731559074210" TEXT="und zwar in dem Fall, wo val ≔ nullptr in dem ItemWrapper gespeichert wurde"/>
|
||||
<node COLOR="#435e98" CREATED="1731559450932" ID="ID_1145602858" MODIFIED="1731608768749" TEXT="opaque-holder.hpp, Zeile 433 ist möglicherweise vom gleichen Problem betroffen">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1731608782409" ID="ID_1577437011" MODIFIED="1731609018193" TEXT="es gibt sogar zwei Probleme hier">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
ein einer einzigen „harmlosen“ Zeile...
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
wenn man die Policy für »unrelated objects« verwendet, wäre BaseP ≡ void* und es gäbe einen Compile-Fehler. <i>Zeigt daß die Tests oberflächlich sind</i>
|
||||
</li>
|
||||
<li>
|
||||
wenn der Payload-Typ SUB ein Pointer ist (auch das wäre theoretisch möglich im Falle der »unrelated objects«) dann würde der Object-Vergleich funktionieren (aber am void* scheitern), wohingegen der Address-Vergleich den Payload-Pointer auspacken, und somit zu einem falschen Urteil kommen würde
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="ksmiletris"/>
|
||||
</node>
|
||||
<node CREATED="1731608770140" ID="ID_1073282986" MODIFIED="1731608781543" TEXT="durch die differenzierte Lösung nun explizit behoben"/>
|
||||
<node COLOR="#435e98" CREATED="1731609027812" ID="ID_209219846" MODIFIED="1731609059104" TEXT="der Trick ist: für den Adress-Vergleich explizit von der Payload die Adresse ziehen">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1731559869128" ID="ID_1223047727" MODIFIED="1731559877774" TEXT="replacable-item.hpp, Zeile 111 ebenso"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1731559083735" ID="ID_1945208616" MODIFIED="1731607982318" TEXT="also: das Problem ist, man braucht die andere (striktere) Vergleichs-Semantik manchmal auch">
|
||||
<font NAME="SansSerif" SIZE="12"/>
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1731560045628" ID="ID_975714348" MODIFIED="1731560051599" TEXT="und zwar in kniffeligen Situationen"/>
|
||||
<node CREATED="1731560052027" ID="ID_5087696" MODIFIED="1731560070981" TEXT="wie self-Assign-Sperre, aber konvertierbar zur Payload und Payload ist ein Pointer"/>
|
||||
<node CREATED="1731560071617" ID="ID_583408006" MODIFIED="1731560124827" TEXT="in solchen Fällen führt die »magische« Dereferenzierung zu einem Fehlurteil"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1731560153334" ID="ID_225688426" MODIFIED="1731607988680" TEXT="Aufgabe ist also: eine Lösung für diese Sonderfälle finden">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node COLOR="#435e98" CREATED="1731560176655" ID="ID_614617889" MODIFIED="1731607991375" TEXT="und zwar eine Lösung, die nicht überraschend ist">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1731600307680" ID="ID_434676407" MODIFIED="1731600338394">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
wir brauchen zwei Semantiken ⟹ also <b>zwei</b> Utilities
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1731600354596" ID="ID_1754449803" MODIFIED="1731600563068" TEXT="tatsächlich ist der flexible Vergleich als Sonderfall zu betrachen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
in den allemeisen Fällen entspricht das, was geprüft wird, tatsächlich dem Begriff "object" aus dem C++ - Standard, also <i>keine Referenz, keine Funktion und nicht void.</i>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1731600820255" ID="ID_180344920" MODIFIED="1731602293404" TEXT="Beschluß: Festlegung der Namen und der Semantik">
|
||||
<arrowlink COLOR="#59586c" DESTINATION="ID_614194653" ENDARROW="Default" ENDINCLINATION="-1423;212;" ID="Arrow_ID_1656634027" STARTARROW="None" STARTINCLINATION="-701;37;"/>
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#b2d2c5" COLOR="#435e98" CREATED="1731624825649" ID="ID_1060913528" MODIFIED="1731624852008" TEXT="Code-Basis verbessert">
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1731467215176" ID="ID_844778131" MODIFIED="1731624889948" TEXT="BufferProviderProtocol_test">
|
||||
<arrowlink COLOR="#73384b" DESTINATION="ID_1574698883" ENDARROW="Default" ENDINCLINATION="-9;41;" ID="Arrow_ID_986253090" STARTARROW="None" STARTINCLINATION="30;3;"/>
|
||||
</node>
|
||||
<node CREATED="1731467215176" ID="ID_74232375" MODIFIED="1731467357686" TEXT="OutputSlotProtocol_test">
|
||||
<node COLOR="#435e98" CREATED="1731467215176" ID="ID_74232375" MODIFIED="1731624889948" TEXT="OutputSlotProtocol_test">
|
||||
<arrowlink COLOR="#73384b" DESTINATION="ID_1574698883" ENDARROW="Default" ENDINCLINATION="-9;41;" ID="Arrow_ID_1250752825" STARTARROW="None" STARTINCLINATION="34;4;"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue