|
Packit |
6d2c1b |
/*
|
|
Packit |
6d2c1b |
* Copyright (c) 2001-2020 Mellanox Technologies, Ltd. All rights reserved.
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* This software is available to you under a choice of one of two
|
|
Packit |
6d2c1b |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit |
6d2c1b |
* General Public License (GPL) Version 2, available from the file
|
|
Packit |
6d2c1b |
* COPYING in the main directory of this source tree, or the
|
|
Packit |
6d2c1b |
* BSD license below:
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* Redistribution and use in source and binary forms, with or
|
|
Packit |
6d2c1b |
* without modification, are permitted provided that the following
|
|
Packit |
6d2c1b |
* conditions are met:
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* - Redistributions of source code must retain the above
|
|
Packit |
6d2c1b |
* copyright notice, this list of conditions and the following
|
|
Packit |
6d2c1b |
* disclaimer.
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* - Redistributions in binary form must reproduce the above
|
|
Packit |
6d2c1b |
* copyright notice, this list of conditions and the following
|
|
Packit |
6d2c1b |
* disclaimer in the documentation and/or other materials
|
|
Packit |
6d2c1b |
* provided with the distribution.
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
6d2c1b |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
6d2c1b |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
6d2c1b |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
6d2c1b |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
6d2c1b |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
6d2c1b |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
6d2c1b |
* SOFTWARE.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#ifndef VMA_LIST_H
|
|
Packit |
6d2c1b |
#define VMA_LIST_H
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#include "vma/util/list.h"
|
|
Packit |
6d2c1b |
#include "vlogger/vlogger.h"
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#define VLIST_DEBUG 0
|
|
Packit |
6d2c1b |
#define VLIST_ID_SIZE 200
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#define vlist_logwarn(log_fmt, log_args...) vlog_printf(VLOG_WARNING, "vlist[%p]:%d:%s() " log_fmt "\n", this, __LINE__, __FUNCTION__, ##log_args)
|
|
Packit |
6d2c1b |
#define vlist_logerr(log_fmt, log_args...) vlog_printf(VLOG_ERROR, "vlist[%p]:%d:%s() " log_fmt "\n", this, __LINE__, __FUNCTION__, ##log_args)
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#if VLIST_DEBUG
|
|
Packit |
6d2c1b |
template <class T, size_t offset(void)>
|
|
Packit |
6d2c1b |
class vma_list_t;
|
|
Packit |
6d2c1b |
#define VLIST_DEBUG_PRINT_ERROR_IS_MEMBER vlist_logerr("Buff is already a member in a list! parent.id=[%s], this.id=[%s]", node_obj->list_id(), this->list_id())
|
|
Packit |
6d2c1b |
#define VLIST_DEBUG_SET_PARENT(node_obj, val) node_obj->parent = val
|
|
Packit |
6d2c1b |
#else
|
|
Packit |
6d2c1b |
#define VLIST_DEBUG_PRINT_ERROR_IS_MEMBER vlist_logerr("Buff is already a member in a list!")
|
|
Packit |
6d2c1b |
#define VLIST_DEBUG_SET_PARENT(node_obj, val)
|
|
Packit |
6d2c1b |
#endif
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#define NODE_OFFSET(_obj_type, _node_name) \
|
|
Packit |
6d2c1b |
((size_t)(&(char &)(((_obj_type *) 1)->_node_name)) - 1)
|
|
Packit |
6d2c1b |
#define GET_NODE(_obj, _obj_type, _offset_func) \
|
|
Packit |
6d2c1b |
((list_node<_obj_type, _offset_func> *) ((size_t)(_obj) + (size_t)(_offset_func())))
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
template <class T, size_t offset(void)>
|
|
Packit |
6d2c1b |
class list_node {
|
|
Packit |
6d2c1b |
public :
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/* head must be the first field! */
|
|
Packit |
6d2c1b |
struct list_head head;
|
|
Packit |
6d2c1b |
T *obj_ptr;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#if VLIST_DEBUG
|
|
Packit |
6d2c1b |
vma_list_t<T, offset> * parent;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
char* list_id() {
|
|
Packit |
6d2c1b |
return this->parent->list_id();
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#endif
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_node() : obj_ptr(NULL) {
|
|
Packit |
6d2c1b |
this->head.next = &this->head;
|
|
Packit |
6d2c1b |
this->head.prev = &this->head;
|
|
Packit |
6d2c1b |
VLIST_DEBUG_SET_PARENT(this, NULL);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/* is_list_member - check if the node is already a member in a list. */
|
|
Packit |
6d2c1b |
bool is_list_member() {
|
|
Packit |
6d2c1b |
return this->head.next != &this->head || this->head.prev != &this->head;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
};
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
template<typename T, size_t offset(void)>
|
|
Packit |
6d2c1b |
class list_iterator_t : public std::iterator<std::random_access_iterator_tag, T, std::ptrdiff_t, T*, T&>
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
public:
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_iterator_t(T* ptr = NULL) : m_ptr(ptr) {}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_iterator_t(const list_iterator_t<T, offset>& iter) : m_ptr(iter.m_ptr) {}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
~list_iterator_t() {}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_iterator_t<T, offset>& operator=(T* ptr) {
|
|
Packit |
6d2c1b |
m_ptr = ptr;
|
|
Packit |
6d2c1b |
return (*this);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_iterator_t<T, offset>& operator=(const list_iterator_t<T, offset>& iter) {
|
|
Packit |
6d2c1b |
m_ptr = iter.m_ptr;
|
|
Packit |
6d2c1b |
return (*this);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
operator bool() const {
|
|
Packit |
6d2c1b |
return m_ptr ? true : false;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
bool operator==(const list_iterator_t<T, offset>& iter) const {
|
|
Packit |
6d2c1b |
return m_ptr == iter.getConstPtr();
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
bool operator!=(const list_iterator_t<T, offset>& iter) const {
|
|
Packit |
6d2c1b |
return m_ptr != iter.getConstPtr();
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_iterator_t<T, offset> operator++(int) {
|
|
Packit |
6d2c1b |
list_iterator_t<T, offset> iter(*this);
|
|
Packit |
6d2c1b |
increment_ptr();
|
|
Packit |
6d2c1b |
return iter;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_iterator_t<T, offset>& operator++() {
|
|
Packit |
6d2c1b |
increment_ptr();
|
|
Packit |
6d2c1b |
return *this;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_iterator_t<T, offset> operator--(int) {
|
|
Packit |
6d2c1b |
list_iterator_t<T, offset> iter(*this);
|
|
Packit |
6d2c1b |
decrement_ptr();
|
|
Packit |
6d2c1b |
return iter;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_iterator_t<T, offset>& operator--() {
|
|
Packit |
6d2c1b |
decrement_ptr();
|
|
Packit |
6d2c1b |
return *this;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
T* operator*() {
|
|
Packit |
6d2c1b |
return m_ptr;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
const T* operator*() const {
|
|
Packit |
6d2c1b |
return m_ptr;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
T* operator->() {
|
|
Packit |
6d2c1b |
return m_ptr;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
T* getPtr() const {
|
|
Packit |
6d2c1b |
return m_ptr;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
const T* getConstPtr() const {
|
|
Packit |
6d2c1b |
return m_ptr;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
private:
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
T* m_ptr;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline void increment_ptr() {
|
|
Packit |
6d2c1b |
m_ptr = ((list_node<T, offset> *)GET_NODE(m_ptr, T, offset)->head.next)->obj_ptr;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline void decrement_ptr() {
|
|
Packit |
6d2c1b |
m_ptr = ((list_node<T, offset> *)GET_NODE(m_ptr, T, offset)->head.prev)->obj_ptr;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
};
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
template <class T, size_t offset(void)>
|
|
Packit |
6d2c1b |
class vma_list_t
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
public:
|
|
Packit |
6d2c1b |
typedef list_iterator_t<T, offset> iterator;
|
|
Packit |
6d2c1b |
vma_list_t() {
|
|
Packit |
6d2c1b |
init_list();
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
void set_id(const char *format, ...) {
|
|
Packit |
6d2c1b |
if (format) {
|
|
Packit |
6d2c1b |
#if VLIST_DEBUG
|
|
Packit |
6d2c1b |
va_list arg;
|
|
Packit |
6d2c1b |
va_start (arg, format);
|
|
Packit |
6d2c1b |
vsnprintf (id, sizeof(id) ,format, arg);
|
|
Packit |
6d2c1b |
va_end (arg);
|
|
Packit |
6d2c1b |
#endif
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
~vma_list_t() {
|
|
Packit |
6d2c1b |
if (!empty()) {
|
|
Packit |
6d2c1b |
vlist_logwarn("Destructor is not supported for non-empty list! size=%zu", m_size);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
vma_list_t<T, offset> (const vma_list_t<T, offset>& other) {
|
|
Packit |
6d2c1b |
if (!other.empty())
|
|
Packit |
6d2c1b |
vlist_logwarn("Copy constructor is not supported for non-empty list! other.size=%zu", other.m_size);
|
|
Packit |
6d2c1b |
init_list();
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
vma_list_t<T, offset>& operator=(const vma_list_t<T, offset>& other) {
|
|
Packit |
6d2c1b |
if (!empty() || !other.empty())
|
|
Packit |
6d2c1b |
vlist_logwarn("Operator= is not supported for non-empty list! size=%zu, other.size=%zu", m_size, other.m_size);
|
|
Packit |
6d2c1b |
if (this != &other) {
|
|
Packit |
6d2c1b |
init_list();
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
return *this;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
T* operator[](size_t idx) const {
|
|
Packit |
6d2c1b |
return get(idx);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline bool empty() const {
|
|
Packit |
6d2c1b |
return m_size == 0;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline size_t size() const {
|
|
Packit |
6d2c1b |
return m_size;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline T* front() const {
|
|
Packit |
6d2c1b |
if (unlikely(empty()))
|
|
Packit |
6d2c1b |
return NULL;
|
|
Packit |
6d2c1b |
return ((list_node<T, offset> *)m_list.head.next)->obj_ptr;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline T* back() const {
|
|
Packit |
6d2c1b |
if (unlikely(empty()))
|
|
Packit |
6d2c1b |
return NULL;
|
|
Packit |
6d2c1b |
/* clang analyzer reports:
|
|
Packit |
6d2c1b |
* Use of memory after it is freed
|
|
Packit |
6d2c1b |
* This issue comes from ~chunk_list_t()
|
|
Packit |
6d2c1b |
* Root cause is unknown.
|
|
Packit |
6d2c1b |
* TODO: Fix based on root cause instead of supressing
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
#ifndef __clang_analyzer__
|
|
Packit |
6d2c1b |
return ((list_node<T, offset> *)m_list.head.prev)->obj_ptr;
|
|
Packit |
6d2c1b |
#endif
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline void pop_front() {
|
|
Packit |
6d2c1b |
erase(front());
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline void pop_back() {
|
|
Packit |
6d2c1b |
erase(back());
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline T* get_and_pop_front() {
|
|
Packit |
6d2c1b |
T* list_front = front();
|
|
Packit |
6d2c1b |
pop_front();
|
|
Packit |
6d2c1b |
return list_front;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline T* get_and_pop_back() {
|
|
Packit |
6d2c1b |
T* list_back = back();
|
|
Packit |
6d2c1b |
pop_back();
|
|
Packit |
6d2c1b |
return list_back;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
void erase(T* obj) {
|
|
Packit |
6d2c1b |
if (unlikely(!obj)) {
|
|
Packit |
6d2c1b |
vlist_logwarn("Got NULL object - ignoring");
|
|
Packit |
6d2c1b |
return;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_node<T, offset> *node_obj = GET_NODE(obj, T, offset);
|
|
Packit |
6d2c1b |
VLIST_DEBUG_SET_PARENT(node_obj, NULL);
|
|
Packit |
6d2c1b |
list_del_init(&node_obj->head);
|
|
Packit |
6d2c1b |
m_size--;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Clear content
|
|
Packit |
6d2c1b |
* Removes all elements from the list container (which are NOT destroyed), and leaving the container with a size of 0.
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* NOTE: we don't expect calling this method in normal situations (it is workaround at application shutdown); Hence, there is no cleanup of node.parent
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
void clear_without_cleanup() {
|
|
Packit |
6d2c1b |
init_list();
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
void push_back(T* obj) {
|
|
Packit |
6d2c1b |
if (unlikely(!obj)) {
|
|
Packit |
6d2c1b |
vlist_logwarn("Got NULL object - ignoring");
|
|
Packit |
6d2c1b |
return;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_node<T, offset> *node_obj = GET_NODE(obj, T, offset);
|
|
Packit |
6d2c1b |
if (unlikely(node_obj->is_list_member())) {
|
|
Packit |
6d2c1b |
VLIST_DEBUG_PRINT_ERROR_IS_MEMBER;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
VLIST_DEBUG_SET_PARENT(node_obj, this);
|
|
Packit |
6d2c1b |
node_obj->obj_ptr = obj;
|
|
Packit |
6d2c1b |
list_add_tail(&node_obj->head, &m_list.head);
|
|
Packit |
6d2c1b |
m_size++;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
void push_front(T* obj) {
|
|
Packit |
6d2c1b |
if (unlikely(!obj)) {
|
|
Packit |
6d2c1b |
vlist_logwarn("Got NULL object - ignoring");
|
|
Packit |
6d2c1b |
return;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_node<T, offset> *node_obj = GET_NODE(obj, T, offset);
|
|
Packit |
6d2c1b |
if (unlikely(node_obj->is_list_member())) {
|
|
Packit |
6d2c1b |
VLIST_DEBUG_PRINT_ERROR_IS_MEMBER;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
VLIST_DEBUG_SET_PARENT(node_obj, this);
|
|
Packit |
6d2c1b |
node_obj->obj_ptr = obj;
|
|
Packit |
6d2c1b |
list_add(&node_obj->head, &m_list.head);
|
|
Packit |
6d2c1b |
m_size++;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
T* get(size_t index) const {
|
|
Packit |
6d2c1b |
if (m_size <= index) {
|
|
Packit |
6d2c1b |
return NULL;
|
|
Packit |
6d2c1b |
} else {
|
|
Packit |
6d2c1b |
list_head* ans = m_list.head.next;
|
|
Packit |
6d2c1b |
for (size_t i = 0 ; i < index ; i++) {
|
|
Packit |
6d2c1b |
ans = ans->next;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
return ((list_node<T, offset> *)ans)->obj_ptr;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
// concatenate 'from' at the head of this list
|
|
Packit |
6d2c1b |
void splice_head(vma_list_t<T, offset>& from) {
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
this->m_size += from.m_size;
|
|
Packit |
6d2c1b |
list_splice(&from.m_list.head, &this->m_list.head);
|
|
Packit |
6d2c1b |
from.init_list();
|
|
Packit |
6d2c1b |
// TODO: in case VLIST_DEBUG, this invalidates parent list of all nodes in the list
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
// concatenate 'from' at the tail of this list
|
|
Packit |
6d2c1b |
void splice_tail(vma_list_t<T, offset>& from) {
|
|
Packit |
6d2c1b |
this->m_size += from.m_size;
|
|
Packit |
6d2c1b |
list_splice_tail(&from.m_list.head, &this->m_list.head);
|
|
Packit |
6d2c1b |
from.init_list();
|
|
Packit |
6d2c1b |
// TODO: in case VLIST_DEBUG, this invalidates parent list of all nodes in the list
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Swap content
|
|
Packit |
6d2c1b |
* Exchanges the content of the container by the content of x, which is another list of the same type. Sizes may differ.
|
|
Packit |
6d2c1b |
*
|
|
Packit |
6d2c1b |
* After the call to this member function, the elements in this container are those which were in x before the call, and
|
|
Packit |
6d2c1b |
* the elements of x are those which were in this. All iterators, references and pointers remain valid for the swapped objects.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
void swap (vma_list_t<T, offset>& x) {
|
|
Packit |
6d2c1b |
vma_list_t<T, offset> temp_list;
|
|
Packit |
6d2c1b |
this->move_to_empty(temp_list);
|
|
Packit |
6d2c1b |
x.move_to_empty(*this);
|
|
Packit |
6d2c1b |
temp_list.move_to_empty(x);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_iterator_t<T, offset> begin() {
|
|
Packit |
6d2c1b |
return list_iterator_t<T, offset>(front());
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_iterator_t<T,offset> end() {
|
|
Packit |
6d2c1b |
return list_iterator_t<T, offset>(NULL);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#if VLIST_DEBUG
|
|
Packit |
6d2c1b |
char* list_id() {
|
|
Packit |
6d2c1b |
return (char*)&id;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
#endif
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
private:
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
list_node<T, offset> m_list;
|
|
Packit |
6d2c1b |
size_t m_size;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#if VLIST_DEBUG
|
|
Packit |
6d2c1b |
char id[VLIST_ID_SIZE];
|
|
Packit |
6d2c1b |
#endif
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
void move_to_empty(vma_list_t<T, offset>& to) {
|
|
Packit |
6d2c1b |
assert(to.empty());
|
|
Packit |
6d2c1b |
to.m_size = this->m_size;
|
|
Packit |
6d2c1b |
list_splice_tail(&this->m_list.head, &to.m_list.head);
|
|
Packit |
6d2c1b |
this->init_list();
|
|
Packit |
6d2c1b |
// TODO: in case VLIST_DEBUG, this invalidates parent list of all nodes in the list
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
void init_list() {
|
|
Packit |
6d2c1b |
m_size = 0;
|
|
Packit |
6d2c1b |
INIT_LIST_HEAD(&m_list.head);
|
|
Packit |
6d2c1b |
#if VLIST_DEBUG
|
|
Packit |
6d2c1b |
id[0] = '\0';
|
|
Packit |
6d2c1b |
#endif
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
};
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#endif /* VMA_LIST_H */
|