Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
linked-elements.hpp
Go to the documentation of this file.
1/*
2 LINKED-ELEMENTS.hpp - configurable intrusive single linked list template
3
4 Copyright (C)
5 2012, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
53#ifndef LIB_LINKED_ELEMENTS_H
54#define LIB_LINKED_ELEMENTS_H
55
56
57#include "lib/error.hpp"
58#include "lib/nocopy.hpp"
59#include "lib/iter-adapter.hpp"
61#include "lib/util.hpp"
62
63#include <utility>
64#include <memory>
65
66
67namespace lib {
68
69 namespace error = lumiera::error;
70 using LERR_(INDEX_BOUNDS);
71 using util::unConst;
72
73
74 namespace linked_elements {
75
83 template<class ALO>
87 {
89
90 using CustomAllocator = ALO;
91 };
92
93
95 template<class N>
97
98
99
100
111 {
112 typedef void* CustomAllocator;
113
117 void
118 dispose (void*)
119 {
120 /* does nothing */
121 }
122
123 template<class TY, typename...ARGS>
124 TY&
125 create (ARGS&&...)
126 {
127 static_assert ("NoOwnership allocation strategy can not allocate elements");
128 } // ... you'll have to do that yourself (that's the whole point of using this strategy)
129 };
130
131 }//(END)namespace linked_elements (predefined policies)
132
133
134
135
136
137
138
139
140
141
142 /****************************************************************************/
154 template
155 < class N
156 , class ALO = linked_elements::OwningHeapAllocated<N>
157 >
159 : ALO
160 {
162
163
164 public:
165
167 {
168 clear();
169 }
170
172 : head_{nullptr}
173 { }
174
175 LinkedElements (LinkedElements const&) = default;
177 : head_{rr.head_}
178 { // possibly transfer ownership
179 rr.head_ = nullptr;
180 }
181
186 explicit
187 LinkedElements (ALO::CustomAllocator allo)
188 : ALO{allo}
189 , head_{nullptr}
190 { }
191
199 template<class IT>
201 : head_{nullptr}
202 {
203 try {
204 pushAll (std::forward<IT> (elements));
205 }
206 catch(...)
207 {
208 WARN (progress, "Failure while populating LinkedElements list. "
209 "All elements will be discarded");
210 clear();
211 throw;
212 } }
213
214
215
217 void
218 clear() noexcept
219 {
220 while (head_)
221 {
222 N* elm = head_;
223 head_ = head_->next;
224 try {
225 ALO::dispose (elm);
226 }
227 ERROR_LOG_AND_IGNORE (progress, "Clean-up of element in LinkedElements list")
228 }
229 }
230
231
236 template<class IT>
237 void
239 {
240 for ( ; elements; ++elements )
241 push (*elements);
242 }
243
244
245
246
251 template<typename TY>
252 TY&
253 push (TY& elm) noexcept
254 {
255 elm.next = head_;
256 head_ = &elm;
257 return elm;
258 }
259
260
261
263 template<class TY =N, typename...ARGS>
264 TY&
265 emplace (ARGS&& ...args)
266 {
267 return push (* ALO::template create<TY> (std::forward<ARGS> (args)...));
268 }
269
270
271
280 {
281 if (not empty())
282 {
283 N* p = head_->next;
284 head_->next = nullptr;
285 while (p)
286 {
287 N& n = *p;
288 p = p->next;
289 push (n);
290 } }
291 return *this;
292 }
293
294
295
296
297 /* === Element access and iteration === */
298
299 N&
300 operator[] (size_t index) const
301 {
302 N* p = head_;
303 while (p and index)
304 {
305 p = p->next;
306 --index;
307 }
308
309 if (!p or index)
310 throw error::Logic ("Attempt to access element beyond the end of LinkedElements list"
311 , LERR_(INDEX_BOUNDS));
312 else
313 return *p;
314 }
315
316
318 N&
319 top() const
320 {
321 REQUIRE (head_, "NIL");
322 return *(unConst(this)->head_);
323 }
324
325
327 size_t
328 size() const
329 {
330 uint count=0;
331 N* p = head_;
332 while (p)
333 {
334 p = p->next;
335 ++count;
336 }
337 return count;
338 }
339
340
341 bool
342 empty() const
343 {
344 return !head_;
345 }
346
347 private:
355 {
357
358 IterationState (N* p =nullptr)
359 : node{p}
360 { }
361
362 /* ==== internal callback API for the iterator ==== */
363
369 void
371 {
372 node = node->next;
373 }
374
376 bool
378 {
379 return bool(node);
380 }
381
382 N&
383 yield() const
384 {
385 REQUIRE (node);
386 return * unConst(this)->node;
387 }
388
389 friend bool
391 {
392 return il.node == ir.node;
393 }
394 };
395
396 public:
399
400
401 iterator begin() { return iterator (head_); }
403 iterator end () { return iterator(); }
404 const_iterator end () const { return const_iterator(); }
405
406 };
407
408
411 template<class N>
412 auto&
413 asLinkedElements (N* const& anchor)
414 {
416 return reinterpret_cast<Linked const&>(anchor);
417 }
418
419
420
421} // namespace lib
422#endif /*LIB_LINKED_ELEMENTS_H*/
A front-end/concept to allow access to custom memory management.
Another Lumiera Forward Iterator building block, based on incorporating a state type as »*State Core*...
Intrusive single linked list, possibly taking ownership of node elements.
TY & push(TY &elm) noexcept
accept the given element and prepend it to the list of elements; depending on the allocation policy,...
LinkedElements & reverse()
Mutate the complete list to change the order of elements.
const_iterator begin() const
N & operator[](size_t index) const
LinkedElements(IT &&elements)
creating a LinkedElements list in RAII-style:
LinkedElements(LinkedElements const &)=default
IterStateWrapper< IterationState, const N & > const_iterator
IterStateWrapper< IterationState, N & > iterator
LinkedElements(LinkedElements &&rr)
TY & emplace(ARGS &&...args)
prepend object of type TY, forwarding ctor args
LinkedElements(ALO::CustomAllocator allo)
void pushAll(IT elements)
convenience shortcut to add all the elements yielded by the given Lumiera Forward Iterator
const_iterator end() const
< Concepts and Adaptors for custom memory management
StdFactory(Allo allo=Allo{})
Create an instance of the adapter factory, forwarding to the embedded standard conforming allocator f...
Types marked with this mix-in may be moved but not copied.
Definition nocopy.hpp:50
Lumiera error handling (C++ interface).
#define ERROR_LOG_AND_IGNORE(_FLAG_, _OP_DESCR_)
convenience shortcut for a sequence of catch blocks just logging and consuming an error.
Definition error.hpp:267
#define LERR_(_NAME_)
Definition error.hpp:45
unsigned int uint
Definition integral.hpp:29
Helper template(s) for creating Lumiera Forward Iterators.
Implementation namespace for support and library code.
IterQueue< T > elements(T const &elm)
convenience free function to build an iterable sequence
auto & asLinkedElements(N *const &anchor)
transiently reinterpret an element pointer as const LinkedElements, allowing to count,...
LumieraError< LERR_(LOGIC)> Logic
Definition error.hpp:207
OBJ * unConst(const OBJ *)
shortcut to save some typing when having to define const and non-const variants of member functions
Definition util.hpp:358
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Iteration is just following the single linked list.
bool checkPoint() const
Iteration-logic: detect iteration end.
friend bool operator==(IterationState const &il, IterationState const &ir)
void iterNext()
Iteration-logic: switch to next position.
Policy for LinkedElements: never create or destroy any elements, only allow to add already existing n...
void dispose(void *)
this policy doesn't take ownership and thus never discards anything
< allocation policies for the LinkedElements list container
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...