Library: allow to reverse intrusive single linked list
Looks like we'll actually retain and use this low-level solution in cases where we just can not afford heap allocations but need to keep polymorphic objects close to one another in memory. Since single linked lists are filled by prepending, it is rather common to need the reversed order of elements for traversal, which can be achieved in linear time. And while we're here, we can modernise the templated emplacement functions
This commit is contained in:
parent
d341f003ca
commit
856d8a3b51
5 changed files with 193 additions and 261 deletions
|
|
@ -73,7 +73,7 @@ namespace lib {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemoryManager(TypeInfo info) : top_(0) { reset(info); }
|
MemoryManager(TypeInfo info) : top_(0) { reset(info); }
|
||||||
~MemoryManager() { purge(); }
|
~MemoryManager() { purge(); }
|
||||||
|
|
||||||
size_t size() const;
|
size_t size() const;
|
||||||
|
|
||||||
|
|
@ -224,8 +224,8 @@ namespace lib {
|
||||||
void*
|
void*
|
||||||
AllocationCluster::initiateAlloc (size_t& slot)
|
AllocationCluster::initiateAlloc (size_t& slot)
|
||||||
{
|
{
|
||||||
if (!slot || slot > typeHandlers_.size() || !handler(slot) )
|
if (!slot or slot > typeHandlers_.size() or !handler(slot) )
|
||||||
return 0; // Memory manager not yet initialised
|
return nullptr; // Memory manager not yet initialised
|
||||||
else
|
else
|
||||||
return handler(slot)->allocate();
|
return handler(slot)->allocate();
|
||||||
}
|
}
|
||||||
|
|
@ -241,7 +241,7 @@ namespace lib {
|
||||||
|
|
||||||
if (slot > typeHandlers_.size())
|
if (slot > typeHandlers_.size())
|
||||||
typeHandlers_.resize(slot);
|
typeHandlers_.resize(slot);
|
||||||
if (!handler(slot))
|
if (not handler(slot))
|
||||||
handler(slot).reset (new MemoryManager (type));
|
handler(slot).reset (new MemoryManager (type));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -290,7 +290,4 @@ namespace lib {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace lib
|
} // namespace lib
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@
|
||||||
#include "lib/scoped-holder.hpp"
|
#include "lib/scoped-holder.hpp"
|
||||||
#include "lib/scoped-holder-transfer.hpp"
|
#include "lib/scoped-holder-transfer.hpp"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -93,46 +94,14 @@ namespace lib {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AllocationCluster ();
|
AllocationCluster ();
|
||||||
~AllocationCluster () noexcept;
|
~AllocationCluster () noexcept;
|
||||||
|
|
||||||
|
|
||||||
template<class TY>
|
template<class TY, typename...ARGS>
|
||||||
TY&
|
TY&
|
||||||
create ()
|
create (ARGS&& ...args)
|
||||||
{
|
{
|
||||||
TY* obj = new(allocation<TY>()) TY();
|
TY* obj = new(allocation<TY>()) TY (std::forward<ARGS> (args)...);
|
||||||
return commit(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TY, typename P0>
|
|
||||||
TY&
|
|
||||||
create (P0& p0)
|
|
||||||
{
|
|
||||||
TY* obj = new(allocation<TY>()) TY (p0);
|
|
||||||
return commit(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TY, typename P0, typename P1>
|
|
||||||
TY&
|
|
||||||
create (P0& p0, P1& p1)
|
|
||||||
{
|
|
||||||
TY* obj = new(allocation<TY>()) TY (p0,p1);
|
|
||||||
return commit(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TY, typename P0, typename P1, typename P2>
|
|
||||||
TY&
|
|
||||||
create (P0& p0, P1& p1, P2& p2)
|
|
||||||
{
|
|
||||||
TY* obj = new(allocation<TY>()) TY (p0,p1,p2);
|
|
||||||
return commit(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TY, typename P0, typename P1, typename P2, typename P3>
|
|
||||||
TY&
|
|
||||||
create (P0& p0, P1& p1, P2& p2, P3& p3)
|
|
||||||
{
|
|
||||||
TY* obj = new(allocation<TY>()) TY (p0,p1,p2,p3);
|
|
||||||
return commit(obj);
|
return commit(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,9 +147,9 @@ namespace lib {
|
||||||
static size_t maxTypeIDs;
|
static size_t maxTypeIDs;
|
||||||
|
|
||||||
|
|
||||||
typedef ScopedPtrHolder<MemoryManager> HMemManager;
|
using HMemManager = ScopedPtrHolder<MemoryManager>;
|
||||||
typedef Allocator_TransferNoncopyable<HMemManager> Allo;
|
using Allo = Allocator_TransferNoncopyable<HMemManager>;
|
||||||
typedef std::vector<HMemManager,Allo> ManagerTable;
|
using ManagerTable = std::vector<HMemManager,Allo>;
|
||||||
|
|
||||||
ManagerTable typeHandlers_; ///< table of active MemoryManager instances
|
ManagerTable typeHandlers_; ///< table of active MemoryManager instances
|
||||||
|
|
||||||
|
|
@ -253,7 +222,7 @@ namespace lib {
|
||||||
setup()
|
setup()
|
||||||
{
|
{
|
||||||
ClassLock<AllocationCluster> guard;
|
ClassLock<AllocationCluster> guard;
|
||||||
if (!id_)
|
if (0 == id_)
|
||||||
id_= ++maxTypeIDs;
|
id_= ++maxTypeIDs;
|
||||||
|
|
||||||
return TypeInfo ((TY*) 0 );
|
return TypeInfo ((TY*) 0 );
|
||||||
|
|
@ -282,7 +251,7 @@ namespace lib {
|
||||||
AllocationCluster::allocation()
|
AllocationCluster::allocation()
|
||||||
{
|
{
|
||||||
void *mem = initiateAlloc (TypeSlot<TY>::get());
|
void *mem = initiateAlloc (TypeSlot<TY>::get());
|
||||||
if (!mem)
|
if (not mem)
|
||||||
mem = initiateAlloc (TypeSlot<TY>::setup(),TypeSlot<TY>::get());
|
mem = initiateAlloc (TypeSlot<TY>::setup(),TypeSlot<TY>::get());
|
||||||
ENSURE (mem);
|
ENSURE (mem);
|
||||||
return mem;
|
return mem;
|
||||||
|
|
@ -311,7 +280,5 @@ namespace lib {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace lib
|
} // namespace lib
|
||||||
#endif
|
#endif /*LIB_ALLOCATION_CLUSTER_H*/
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
** Intrusive single linked list with optional ownership.
|
** Intrusive single linked list with optional ownership.
|
||||||
** This helper template allows to attach a number of tightly integrated
|
** This helper template allows to attach a number of tightly integrated
|
||||||
** elements with low overhead. Typically, these elements are to be attached
|
** elements with low overhead. Typically, these elements are to be attached
|
||||||
** once and never changed. Optionally, elements can be created using a
|
** once and never changed. Optionally, elements can be created using a
|
||||||
** custom allocation scheme; the holder might also take ownership. These
|
** custom allocation scheme; the holder might also take ownership. These
|
||||||
** variations in functionality are controlled by policy templates.
|
** variations in functionality are controlled by policy templates.
|
||||||
**
|
**
|
||||||
|
|
@ -37,8 +37,8 @@
|
||||||
** - convenient access through Lumiera Forward Iterators
|
** - convenient access through Lumiera Forward Iterators
|
||||||
** - the need to integrate tightly with a custom allocator
|
** - the need to integrate tightly with a custom allocator
|
||||||
**
|
**
|
||||||
** @note this linked list container is \em intrusive and thus needs the help
|
** @note this linked list container is _intrusive_ and thus needs the help
|
||||||
** of the element type, which must provide a pointer member \c next.
|
** of the element type, which must *provide a pointer member* `next`.
|
||||||
** Consequently, each such node element can't be member in
|
** Consequently, each such node element can't be member in
|
||||||
** multiple collections at the same time
|
** multiple collections at the same time
|
||||||
** @note as usual, any iterator relies on the continued existence and
|
** @note as usual, any iterator relies on the continued existence and
|
||||||
|
|
@ -65,8 +65,7 @@
|
||||||
#include "lib/iter-adapter.hpp"
|
#include "lib/iter-adapter.hpp"
|
||||||
#include "lib/util.hpp"
|
#include "lib/util.hpp"
|
||||||
|
|
||||||
#include <boost/static_assert.hpp>
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace lib {
|
namespace lib {
|
||||||
|
|
@ -81,8 +80,11 @@ namespace lib {
|
||||||
/**
|
/**
|
||||||
* Policy for LinkedElements: taking ownership
|
* Policy for LinkedElements: taking ownership
|
||||||
* and possibly creating heap allocated Nodes
|
* and possibly creating heap allocated Nodes
|
||||||
|
* @note is util::MoveOnly to enforce ownership
|
||||||
|
* on behalf of LinkedElements
|
||||||
*/
|
*/
|
||||||
struct OwningHeapAllocated
|
struct OwningHeapAllocated
|
||||||
|
: util::MoveOnly
|
||||||
{
|
{
|
||||||
typedef void* CustomAllocator;
|
typedef void* CustomAllocator;
|
||||||
|
|
||||||
|
|
@ -99,69 +101,11 @@ namespace lib {
|
||||||
|
|
||||||
/** this policy creates new elements
|
/** this policy creates new elements
|
||||||
* simply by heap allocation */
|
* simply by heap allocation */
|
||||||
template<class TY>
|
template<class TY, typename...ARGS>
|
||||||
TY&
|
TY&
|
||||||
create ()
|
create (ARGS&& ...args)
|
||||||
{
|
{
|
||||||
return *new TY();
|
return *new TY (std::forward<ARGS> (args)...);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class TY, typename A1>
|
|
||||||
TY& //____________________________________________
|
|
||||||
create (A1 a1) ///< create object of type TY, using 1-arg ctor
|
|
||||||
{
|
|
||||||
return *new TY(a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
|
||||||
, typename A2
|
|
||||||
>
|
|
||||||
TY& //____________________________________________
|
|
||||||
create (A1 a1, A2 a2) ///< create object of type TY, using 2-arg ctor
|
|
||||||
{
|
|
||||||
return *new TY(a1,a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
|
||||||
, typename A2
|
|
||||||
, typename A3
|
|
||||||
>
|
|
||||||
TY& //____________________________________________
|
|
||||||
create (A1 a1, A2 a2, A3 a3) ///< create object of type TY, using 3-arg ctor
|
|
||||||
{
|
|
||||||
return *new TY(a1,a2,a3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
|
||||||
, typename A2
|
|
||||||
, typename A3
|
|
||||||
, typename A4
|
|
||||||
>
|
|
||||||
TY& //____________________________________________
|
|
||||||
create (A1 a1, A2 a2, A3 a3, A4 a4) ///< create object of type TY, using 4-arg ctor
|
|
||||||
{
|
|
||||||
return *new TY(a1,a2,a3,a4);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
|
||||||
, typename A2
|
|
||||||
, typename A3
|
|
||||||
, typename A4
|
|
||||||
, typename A5
|
|
||||||
>
|
|
||||||
TY& //____________________________________________
|
|
||||||
create (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) ///< create object of type TY, using 5-arg ctor
|
|
||||||
{
|
|
||||||
return *new TY(a1,a2,a3,a4,a5);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -191,6 +135,13 @@ namespace lib {
|
||||||
{
|
{
|
||||||
/* does nothing */
|
/* does nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class TY, typename...ARGS>
|
||||||
|
TY&
|
||||||
|
create (ARGS&&...)
|
||||||
|
{
|
||||||
|
static_assert ("NoOwnership allocation strategy can not allocate elements");
|
||||||
|
} // ... you'll have to do that yourself (that's the whole point of using this strategy)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -234,55 +185,11 @@ namespace lib {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class TY>
|
template<class TY, typename...ARGS>
|
||||||
TY& //__________________________________________
|
TY&
|
||||||
create () ///< place object of type TY, by default ctor
|
create (ARGS&& ...args)
|
||||||
{
|
{
|
||||||
return cluster_.create<TY>();
|
return cluster_.create<TY> (std::forward<ARGS> (args)...);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class TY, typename A1>
|
|
||||||
TY& //___________________________________________
|
|
||||||
create (A1 a1) ///< place object of type TY, using 1-arg ctor
|
|
||||||
{
|
|
||||||
return cluster_.create<TY> (a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
|
||||||
, typename A2
|
|
||||||
>
|
|
||||||
TY& //___________________________________________
|
|
||||||
create (A1 a1, A2 a2) ///< place object of type TY, using 2-arg ctor
|
|
||||||
{
|
|
||||||
return cluster_.create<TY> (a1,a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
|
||||||
, typename A2
|
|
||||||
, typename A3
|
|
||||||
>
|
|
||||||
TY& //___________________________________________
|
|
||||||
create (A1 a1, A2 a2, A3 a3) ///< place object of type TY, using 3-arg ctor
|
|
||||||
{
|
|
||||||
return cluster_.create<TY> (a1,a2,a3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
|
||||||
, typename A2
|
|
||||||
, typename A3
|
|
||||||
, typename A4
|
|
||||||
>
|
|
||||||
TY& //___________________________________________
|
|
||||||
create (A1 a1, A2 a2, A3 a3, A4 a4) ///< place object of type TY, using 4-arg ctor
|
|
||||||
{
|
|
||||||
return cluster_.create<TY> (a1,a2,a3,a4);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -315,8 +222,7 @@ namespace lib {
|
||||||
, class ALO = linked_elements::OwningHeapAllocated
|
, class ALO = linked_elements::OwningHeapAllocated
|
||||||
>
|
>
|
||||||
class LinkedElements
|
class LinkedElements
|
||||||
: util::NonCopyable
|
: ALO
|
||||||
, ALO
|
|
||||||
{
|
{
|
||||||
N* head_;
|
N* head_;
|
||||||
|
|
||||||
|
|
@ -332,6 +238,13 @@ namespace lib {
|
||||||
: head_{nullptr}
|
: head_{nullptr}
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
LinkedElements (LinkedElements const&) = default;
|
||||||
|
LinkedElements (LinkedElements&& rr)
|
||||||
|
: head_{rr.head_}
|
||||||
|
{ // possibly transfer ownership
|
||||||
|
rr.head_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/** @param allo custom allocator or memory manager
|
/** @param allo custom allocator or memory manager
|
||||||
* to be used by the policy for creating and
|
* to be used by the policy for creating and
|
||||||
* discarding of node elements
|
* discarding of node elements
|
||||||
|
|
@ -349,11 +262,11 @@ namespace lib {
|
||||||
* causes already created elements to be destroyed
|
* causes already created elements to be destroyed
|
||||||
*/
|
*/
|
||||||
template<class IT>
|
template<class IT>
|
||||||
LinkedElements (IT elements)
|
LinkedElements (IT&& elements)
|
||||||
: head_{nullptr}
|
: head_{nullptr}
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
pushAll (elements);
|
pushAll (std::forward<IT> (elements));
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
|
@ -410,75 +323,46 @@ namespace lib {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< class TY >
|
// template< class TY =N>
|
||||||
TY& //_________________________________________
|
// TY& //_________________________________________
|
||||||
pushNew () ///< add object of type TY, using 0-arg ctor
|
// emplace () ///< add object of type TY, using 0-arg ctor
|
||||||
|
// {
|
||||||
|
// return push (ALO::template create<TY>());
|
||||||
|
// }
|
||||||
|
|
||||||
|
/** prepend object of type TY, forwarding ctor args */
|
||||||
|
template<class TY =N, typename...ARGS>
|
||||||
|
TY&
|
||||||
|
emplace (ARGS&& ...args)
|
||||||
{
|
{
|
||||||
return push (ALO::template create<TY>());
|
return push (ALO::template create<TY> (std::forward<ARGS> (args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
/**
|
||||||
>
|
* Mutate the complete list to change the order of elements.
|
||||||
TY& //_________________________________________
|
* @remark since pushing prepends, elements are initially in reverse order
|
||||||
pushNew (A1 a1) ///< add object of type TY, using 1-arg ctor
|
* @warning this operation invalidates iterators and has O(n) cost;
|
||||||
|
* ownership and elements themselves are not affected.
|
||||||
|
*/
|
||||||
|
LinkedElements&
|
||||||
|
reverse()
|
||||||
{
|
{
|
||||||
return push (ALO::template create<TY>(a1));
|
if (not empty())
|
||||||
|
{
|
||||||
|
N* p = head_->next;
|
||||||
|
head_->next = nullptr;
|
||||||
|
while (p)
|
||||||
|
{
|
||||||
|
N& n = *p;
|
||||||
|
p = p->next;
|
||||||
|
push (n);
|
||||||
|
} }
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
|
||||||
, typename A2
|
|
||||||
>
|
|
||||||
TY& //_________________________________________
|
|
||||||
pushNew (A1 a1, A2 a2) ///< add object of type TY, using 2-arg ctor
|
|
||||||
{
|
|
||||||
return push (ALO::template create<TY>(a1,a2));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
|
||||||
, typename A2
|
|
||||||
, typename A3
|
|
||||||
>
|
|
||||||
TY& //_________________________________________
|
|
||||||
pushNew (A1 a1, A2 a2, A3 a3) ///< add object of type TY, using 3-arg ctor
|
|
||||||
{
|
|
||||||
return push (ALO::template create<TY>(a1,a2,a3));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
|
||||||
, typename A2
|
|
||||||
, typename A3
|
|
||||||
, typename A4
|
|
||||||
>
|
|
||||||
TY& //_________________________________________
|
|
||||||
pushNew (A1 a1, A2 a2, A3 a3, A4 a4) ///< add object of type TY, using 4-arg ctor
|
|
||||||
{
|
|
||||||
return push (ALO::template create<TY>(a1,a2,a3,a4));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template< class TY
|
|
||||||
, typename A1
|
|
||||||
, typename A2
|
|
||||||
, typename A3
|
|
||||||
, typename A4
|
|
||||||
, typename A5
|
|
||||||
>
|
|
||||||
TY& //_________________________________________
|
|
||||||
pushNew (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) ///< add object of type TY, using 5-arg ctor
|
|
||||||
{
|
|
||||||
return push (ALO::template create<TY>(a1,a2,a3,a4,a5));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* === Element access and iteration === */
|
/* === Element access and iteration === */
|
||||||
|
|
@ -487,13 +371,13 @@ namespace lib {
|
||||||
operator[] (size_t index) const
|
operator[] (size_t index) const
|
||||||
{
|
{
|
||||||
N* p = head_;
|
N* p = head_;
|
||||||
while (p && index)
|
while (p and index)
|
||||||
{
|
{
|
||||||
p = p->next;
|
p = p->next;
|
||||||
--index;
|
--index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p || index)
|
if (!p or index)
|
||||||
throw error::Logic ("Attempt to access element beyond the end of LinkedElements list"
|
throw error::Logic ("Attempt to access element beyond the end of LinkedElements list"
|
||||||
, LERR_(INDEX_BOUNDS));
|
, LERR_(INDEX_BOUNDS));
|
||||||
else
|
else
|
||||||
|
|
@ -501,9 +385,18 @@ namespace lib {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @warning unchecked */
|
||||||
|
N&
|
||||||
|
top() const
|
||||||
|
{
|
||||||
|
REQUIRE (head_, "NIL");
|
||||||
|
return *(unConst(this)->head_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @warning traverses to count the elements */
|
/** @warning traverses to count the elements */
|
||||||
size_t
|
size_t
|
||||||
size () const
|
size() const
|
||||||
{
|
{
|
||||||
uint count=0;
|
uint count=0;
|
||||||
N* p = head_;
|
N* p = head_;
|
||||||
|
|
@ -517,7 +410,7 @@ namespace lib {
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
empty () const
|
empty() const
|
||||||
{
|
{
|
||||||
return !head_;
|
return !head_;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
////#include "lib/time/timequant.hpp"
|
////#include "lib/time/timequant.hpp"
|
||||||
////#include "lib/format-cout.hpp"
|
////#include "lib/format-cout.hpp"
|
||||||
#include "lib/depend.hpp"
|
#include "lib/depend.hpp"
|
||||||
//#include "lib/itertools.hpp"
|
#include "lib/itertools.hpp"
|
||||||
//#include "lib/util-coll.hpp"
|
//#include "lib/util-coll.hpp"
|
||||||
#include "lib/test/test-helper.hpp"
|
#include "lib/test/test-helper.hpp"
|
||||||
//#include "lib/util.hpp"
|
//#include "lib/util.hpp"
|
||||||
|
|
@ -115,8 +115,19 @@ namespace test {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @deprecated this setup is confusing and dangerous (instance identity is ambiguous)
|
||||||
lib::Depend<MockDispatcherTable> mockDispatcher;
|
lib::Depend<MockDispatcherTable> mockDispatcher;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline auto
|
||||||
|
defineBottomProvision()
|
||||||
|
{
|
||||||
|
// return lib::singleValIterator(
|
||||||
|
// JobTicket::buildProvision (
|
||||||
|
// ));
|
||||||
|
}
|
||||||
|
|
||||||
}//(End)internal test helpers....
|
}//(End)internal test helpers....
|
||||||
|
|
||||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1221
|
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1221
|
||||||
|
|
@ -134,7 +145,9 @@ namespace test {
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MockJobTicket() { };
|
// MockJobTicket()
|
||||||
|
// : JobTicket{JobTicket::Provisions{defineBottomProvision()}}
|
||||||
|
// { };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
@ -69,15 +69,15 @@ namespace test{
|
||||||
{
|
{
|
||||||
Nummy* next;
|
Nummy* next;
|
||||||
|
|
||||||
Nummy()
|
Nummy()
|
||||||
: Dummy()
|
: Dummy()
|
||||||
, next(0)
|
, next{0}
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
Nummy (int i)
|
Nummy (int i)
|
||||||
: Dummy(i)
|
: Dummy{i}
|
||||||
, next(0)
|
, next{0}
|
||||||
{
|
{
|
||||||
if (i == exception_trigger)
|
if (i == exception_trigger)
|
||||||
throw error::Fatal("simulated error", LERR_(PROVOKED_FAILURE));
|
throw error::Fatal("simulated error", LERR_(PROVOKED_FAILURE));
|
||||||
|
|
@ -102,7 +102,7 @@ namespace test{
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to produce a pre-determined series
|
* Helper to produce a pre-determined series
|
||||||
* of objects to populate a LinkedElements list.
|
* of objects to populate a LinkedElements list.
|
||||||
* @note just happily heap allocating new instances
|
* @note just happily heap allocating new instances
|
||||||
* and handing them out. The LinkedElements list
|
* and handing them out. The LinkedElements list
|
||||||
|
|
@ -140,7 +140,6 @@ namespace test{
|
||||||
class Populator
|
class Populator
|
||||||
: public NummyGenerator::iterator
|
: public NummyGenerator::iterator
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit
|
explicit
|
||||||
Populator (uint numElms)
|
Populator (uint numElms)
|
||||||
|
|
@ -165,13 +164,13 @@ namespace test{
|
||||||
|
|
||||||
|
|
||||||
/// default case: ownership for heap allocated nodes
|
/// default case: ownership for heap allocated nodes
|
||||||
typedef LinkedElements<Nummy> List;
|
using List = LinkedElements<Nummy>;
|
||||||
|
|
||||||
/// managing existing node elements without taking ownership
|
/// managing existing node elements without taking ownership
|
||||||
typedef LinkedElements<Nummy, linked_elements::NoOwnership> ListNotOwner;
|
using ListNotOwner = LinkedElements<Nummy, linked_elements::NoOwnership>;
|
||||||
|
|
||||||
/// creating nodes in-place, using a custom allocator for creation and disposal
|
/// creating nodes in-place, using a custom allocator for creation and disposal
|
||||||
typedef LinkedElements<Nummy, linked_elements::UseAllocationCluster> ListCustomAllocated;
|
using ListCustomAllocated = LinkedElements<Nummy, linked_elements::UseAllocationCluster>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -188,6 +187,7 @@ namespace test{
|
||||||
{
|
{
|
||||||
simpleUsage();
|
simpleUsage();
|
||||||
iterating();
|
iterating();
|
||||||
|
reverseList();
|
||||||
|
|
||||||
verify_nonOwnership();
|
verify_nonOwnership();
|
||||||
verify_ExceptionSafety();
|
verify_ExceptionSafety();
|
||||||
|
|
@ -207,11 +207,11 @@ namespace test{
|
||||||
CHECK (0 == elements.size());
|
CHECK (0 == elements.size());
|
||||||
CHECK (0 == Dummy::checksum());
|
CHECK (0 == Dummy::checksum());
|
||||||
|
|
||||||
elements.pushNew<Nummy>(1);
|
elements.emplace<Nummy>(1);
|
||||||
elements.pushNew<Nummy>(2);
|
elements.emplace<Nummy>(2);
|
||||||
elements.pushNew<Nummy>(3);
|
elements.emplace<Nummy>(3);
|
||||||
elements.pushNew<Nummy>(4);
|
elements.emplace<Nummy>(4);
|
||||||
elements.pushNew<Nummy>(5);
|
elements.emplace<Nummy>(5);
|
||||||
CHECK (!isnil (elements));
|
CHECK (!isnil (elements));
|
||||||
CHECK (5 == elements.size());
|
CHECK (5 == elements.size());
|
||||||
CHECK (0 != Dummy::checksum());
|
CHECK (0 != Dummy::checksum());
|
||||||
|
|
@ -227,9 +227,9 @@ namespace test{
|
||||||
CHECK (0 == elements.size());
|
CHECK (0 == elements.size());
|
||||||
CHECK (0 == Dummy::checksum());
|
CHECK (0 == Dummy::checksum());
|
||||||
|
|
||||||
elements.pushNew<Nummy>();
|
elements.emplace<Nummy>();
|
||||||
elements.pushNew<Nummy>();
|
elements.emplace<Nummy>();
|
||||||
elements.pushNew<Nummy>();
|
elements.emplace<Nummy>();
|
||||||
|
|
||||||
CHECK (3 == elements.size());
|
CHECK (3 == elements.size());
|
||||||
CHECK (0 != Dummy::checksum());
|
CHECK (0 != Dummy::checksum());
|
||||||
|
|
@ -245,9 +245,9 @@ namespace test{
|
||||||
{
|
{
|
||||||
List elements;
|
List elements;
|
||||||
for (uint i=1; i<=NUM_ELEMENTS; ++i)
|
for (uint i=1; i<=NUM_ELEMENTS; ++i)
|
||||||
elements.pushNew<Nummy>(i);
|
elements.emplace<Nummy>(i);
|
||||||
|
|
||||||
// since elements where pushed,
|
// since elements where pushed,
|
||||||
// they should appear in reversed order
|
// they should appear in reversed order
|
||||||
int check=NUM_ELEMENTS;
|
int check=NUM_ELEMENTS;
|
||||||
List::iterator ii = elements.begin();
|
List::iterator ii = elements.begin();
|
||||||
|
|
@ -293,6 +293,68 @@ namespace test{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
reverseList()
|
||||||
|
{
|
||||||
|
CHECK (0 == Dummy::checksum());
|
||||||
|
{
|
||||||
|
List list;
|
||||||
|
CHECK (isnil (list));
|
||||||
|
list.reverse();
|
||||||
|
CHECK (isnil (list));
|
||||||
|
CHECK (0 == Dummy::checksum());
|
||||||
|
|
||||||
|
list.emplace<Nummy>(1);
|
||||||
|
CHECK (not isnil (list));
|
||||||
|
CHECK (1 == list[0].getVal());
|
||||||
|
CHECK (1 == Dummy::checksum());
|
||||||
|
list.reverse();
|
||||||
|
CHECK (1 == Dummy::checksum());
|
||||||
|
CHECK (1 == list[0].getVal());
|
||||||
|
CHECK (not isnil (list));
|
||||||
|
|
||||||
|
list.emplace<Nummy>(2);
|
||||||
|
CHECK (not isnil (list));
|
||||||
|
CHECK (2 == list.size());
|
||||||
|
CHECK (2 == list[0].getVal());
|
||||||
|
CHECK (2+1 == Dummy::checksum());
|
||||||
|
list.reverse();
|
||||||
|
CHECK (1+2 == Dummy::checksum());
|
||||||
|
CHECK (1 == list[0].getVal());
|
||||||
|
CHECK (2 == list.size());
|
||||||
|
|
||||||
|
list.emplace<Nummy>(3);
|
||||||
|
CHECK (3 == list.size());
|
||||||
|
CHECK (3 == list.top().getVal());
|
||||||
|
CHECK (3+1+2 == Dummy::checksum());
|
||||||
|
list.reverse();
|
||||||
|
CHECK (2 == list[0].getVal());
|
||||||
|
CHECK (1 == list[1].getVal());
|
||||||
|
CHECK (3 == list[2].getVal());
|
||||||
|
List::iterator ii = list.begin();
|
||||||
|
CHECK (2 == ii->getVal());
|
||||||
|
++ii;
|
||||||
|
CHECK (1 == ii->getVal());
|
||||||
|
++ii;
|
||||||
|
CHECK (3 == ii->getVal());
|
||||||
|
++ii;
|
||||||
|
CHECK (isnil (ii));
|
||||||
|
CHECK (2+1+3 == Dummy::checksum());
|
||||||
|
|
||||||
|
list.emplace<Nummy>(4);
|
||||||
|
CHECK (4 == list.top().getVal());
|
||||||
|
CHECK (3 == list[3].getVal());
|
||||||
|
list.reverse();
|
||||||
|
CHECK (3 == list[0].getVal());
|
||||||
|
CHECK (1 == list[1].getVal());
|
||||||
|
CHECK (2 == list[2].getVal());
|
||||||
|
CHECK (4 == list[3].getVal());
|
||||||
|
CHECK (3+1+2+4 == Dummy::checksum());
|
||||||
|
}
|
||||||
|
CHECK (0 == Dummy::checksum());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @test add some node elements to the LinkedElements list
|
/** @test add some node elements to the LinkedElements list
|
||||||
* but without taking ownership or performing any
|
* but without taking ownership or performing any
|
||||||
* memory management. This usage pattern is helpful
|
* memory management. This usage pattern is helpful
|
||||||
|
|
@ -346,11 +408,11 @@ namespace test{
|
||||||
|
|
||||||
__triggerErrorAt(3);
|
__triggerErrorAt(3);
|
||||||
|
|
||||||
elements.pushNew<Nummy>(1);
|
elements.emplace<Nummy>(1);
|
||||||
elements.pushNew<Nummy>(2);
|
elements.emplace<Nummy>(2);
|
||||||
CHECK (1+2 == Dummy::checksum());
|
CHECK (1+2 == Dummy::checksum());
|
||||||
|
|
||||||
VERIFY_ERROR (PROVOKED_FAILURE, elements.pushNew<Nummy>(3) );
|
VERIFY_ERROR (PROVOKED_FAILURE, elements.emplace<Nummy>(3) );
|
||||||
CHECK (1+2 == Dummy::checksum());
|
CHECK (1+2 == Dummy::checksum());
|
||||||
CHECK (2 == elements.size());
|
CHECK (2 == elements.size());
|
||||||
|
|
||||||
|
|
@ -420,9 +482,9 @@ namespace test{
|
||||||
|
|
||||||
ListCustomAllocated elements(allocator);
|
ListCustomAllocated elements(allocator);
|
||||||
|
|
||||||
elements.pushNew<Num<1>> (2);
|
elements.emplace<Num<1>> (2);
|
||||||
elements.pushNew<Num<3>> (4,5);
|
elements.emplace<Num<3>> (4,5);
|
||||||
elements.pushNew<Num<6>> (7,8,9);
|
elements.emplace<Num<6>> (7,8,9);
|
||||||
|
|
||||||
CHECK (sum(9) == Dummy::checksum());
|
CHECK (sum(9) == Dummy::checksum());
|
||||||
CHECK (3 == allocator.size());
|
CHECK (3 == allocator.size());
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue