Commit 3910cd13 authored by Gauthier Quesnel's avatar Gauthier Quesnel
Browse files

next5

parent a9ce09ba
Pipeline #2218 failed with stage
in 1 minute and 10 seconds
// Copyright (c) 2019 INRA Distributed under the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef ORG_VLEPROJECT_BITS_ALLOCATOR_HPP
#define ORG_VLEPROJECT_BITS_ALLOCATOR_HPP
#include <memory>
#include <cstdint>
namespace bits {
template<class T, std::size_t capacity = 1024>
class fixed_memory_allocator
{
union block
{
block* next;
typename std::aligned_storage<sizeof(T), alignof(T)>::type storage;
};
class buffer
{
static constexpr std::size_t block_size = sizeof(T) > sizeof(block)
? sizeof(T)
: sizeof(block);
std::uint8_t data[block_size * capacity];
};
buffer data;
int free_head = -1;
int size = 0;
public:
fixed_memory_allocator() = default;
fixed_memory_allocator(fixed_memory_allocator&&) = delete;
fixed_memory_allocator(const fixed_memory_allocator&) = delete;
fixed_memory_allocator operator=(fixed_memory_allocator&&) = delete;
fixed_memory_allocator operator=(const fixed_memory_allocator&) = delete;
~fixed_memory_allocator() = default;
T* allocate()
{
if (size >= capacity)
throw std::bad_alloc();
block* new_alloc;
if (free_head >= 0) {
new_alloc = free_head;
free_head = data[free_head]->next;
} else
new_alloc = reinterpret_cast<block*>(&data[size++]);
return reinterpret_cast<T*>(new_alloc);
}
void deallocate(T* pointer) noexcept
{
block* blk = reinterpret_cast<block*>(pointer);
blk->next = free_head;
free_head = blk;
}
};
template<class T, std::size_t capacity = 1024>
class block_memory_allocator
{
union block
{
block* next;
typename std::aligned_storage<sizeof(T), alignof(T)>::type storage;
};
class buffer
{
static constexpr std::size_t block_size = sizeof(T) > sizeof(block)
? sizeof(T)
: sizeof(block);
std::uint8_t data[block_size * capacity];
public:
const buffer* next;
buffer(buffer* next_) noexcept
: next(next_)
{}
T* get_block(int index) noexcept
{
return reinterpret_cast<T*>(&data[block_size * index]);
}
};
block* free_head = nullptr;
buffer* first_buffer = nullptr;
std::size_t size = capacity;
public:
block_memory_allocator() noexcept = default;
block_memory_allocator(const block_memory_allocator&) noexcept = default;
block_memory_allocator& operator=(const block_memory_allocator&) noexcept =
default;
block_memory_allocator(block_memory_allocator&& other) noexcept
: free_head(other.free_head)
, first_buffer(other.first_buffer)
, size(other.size)
{
other.free_head = nullptr;
other.first_buffer = nullptr;
other.size = { 0 };
}
block_memory_allocator& operator=(block_memory_allocator&& other) noexcept
{
if (this != &other) {
while (first_buffer) {
auto* buffer = first_buffer;
first_buffer = buffer->next;
delete buffer;
}
free_head = other.free_head;
first_buffer = other.first_buffer;
size = other.size;
other.free_head = nullptr;
other.first_buffer = nullptr;
other.size = { 0 };
}
return *this;
}
~block_memory_allocator() noexcept
{
while (first_buffer) {
auto* buffer = first_buffer;
first_buffer = buffer->next;
delete buffer;
}
}
T* allocate()
{
if (free_head) {
block* block = free_head;
free_head = block->next;
return reinterpret_cast<T*>(block);
}
if (size >= capacity) {
first_buffer = new buffer(first_buffer);
size = 0;
}
return first_buffer->getBlock(size++);
}
void deallocate(T* pointer) noexcept
{
block* blk = reinterpret_cast<block*>(pointer);
blk->next = free_head;
free_head = blk;
}
};
template<class T, std::size_t capacity = 1024>
class fixed_node_allocator : private fixed_memory_allocator<T, capacity>
{
public:
using value_type = T;
using size_type = std::size_t;
using propagate_on_container_move_assignment = std::true_type;
using difference_type = std::ptrdiff_t;
T* allocate(size_type n, const void* hint = 0)
{
if (n != 1 || hint)
throw std::bad_alloc();
return fixed_node_allocator<T, capacity>::allocate();
}
void deallocate(T* p, size_type n)
{
fixed_node_allocator<T, capacity>::deallocate(p);
}
void construct(T* p, const T& val)
{
new (p) T(val);
}
void destroy(T* p)
{
p->~T();
}
};
template<class T, std::size_t capacity = 1024>
class block_node_allocator : private block_memory_allocator<T, capacity>
{
public:
using value_type = T;
using size_type = std::size_t;
using propagate_on_container_move_assignment = std::true_type;
using difference_type = std::ptrdiff_t;
T* allocate(size_type n, const void* hint = 0)
{
if (n != 1 || hint)
throw std::bad_alloc();
return block_node_allocator<T, capacity>::allocate();
}
void deallocate(T* p, size_type n)
{
block_node_allocator<T, capacity>::deallocate(p);
}
void construct(T* p, const T& val)
{
new (p) T(val);
}
void destroy(T* p)
{
p->~T();
}
};
} // bits
#endif // ORG_VLEPROJECT_BITS_ALLOCATOR_HPP
......@@ -5,19 +5,26 @@
#ifndef ORG_VLEPROJECT_BITS_TRIVIAL_LIST_HPP
#define ORG_VLEPROJECT_BITS_TRIVIAL_LIST_HPP
#include <bits/data-array.hpp>
#include <bits/allocator.hpp>
#include <cassert>
#include <forward_list>
#include <list>
namespace bits {
/* Maybe we can call it trivial_flat_forward_list ? */
template<typename T>
struct flat_forward_list
{
using accessor_type = int;
struct accessor_type
{
int head = -1;
};
static_assert(std::is_trivial<T>::value,
"flat_forward_list needs trivial type");
static_assert(std::is_trivial<T>::value &&
std::is_standard_layout<T>::value,
"flat_forward_list needs std::is_pod type");
struct item
{
......@@ -25,6 +32,78 @@ struct flat_forward_list
int next;
};
// class iterator
// {
// using iterator_category = std::forward_iterator_tag;
// using value_type = T;
// using difference_type = std::ptrdiff_t;
// using pointer = T*;
// using reference = T&;
// iterator(item* items_, int id_)
// : items(items_)
// , id(id_)
// {}
// iterator(const iterator&) = default;
// iterator(iterator&&) = default;
// iterator operator=(const iterator&) = default;
// iterator operator=(iterator&&) = default;
// iterator operator++(int)
// {
// if (id == -1)
// return iterator(items, -1);
// iterator copy(*this);
// id = items[id].next;
// return copy;
// }
// iterator& operator++()
// {
// if (id == -1)
// return iterator(items, -1);
// id = items[id].next;
// return *this;
// }
// const pointer operator->() const
// {
// return &items[id];
// }
// reference operator*() const
// {
// return items[id];
// }
// friend void swap(iterator& lhs, iterator& rhs)
// {
// auto items_ = lhs.items;
// auto id_ = lhs.id;
// lhs.items = rhs.items;
// lhs.id = rhs.id;
// rhs.items = items_;
// rhs.id = id_;
// }
// friend bool operator==(const iterator& lhs, const iterator& rhs)
// {
// return lhs.id == rhs.id;
// }
// friend bool operator!=(const iterator& lhs, const iterator& rhs)
// {
// return !(lhs.id == rhs.id);
// }
// item* items;
// int id;
// };
item* items = nullptr;
int size = 0;
int free_head = -1;
......@@ -51,6 +130,13 @@ struct flat_forward_list
items = new item[capacity_];
}
// iterator begin(int head) noexcept
// {
// return iterator(items, head);
// }
// iterator end()
[[nodiscard]] int alloc() noexcept
{
int new_head;
......@@ -65,27 +151,28 @@ struct flat_forward_list
return new_head;
}
[[nodiscard]] accessor_type push_front(int head, T id) noexcept
[[nodiscard]] accessor_type push_front(accessor_type list, T id) noexcept
{
int new_head = alloc();
items[new_head].id = id;
items[new_head].next = head;
items[new_head].next = list.head;
list.head = new_head;
return new_head;
return list;
}
[[nodiscard]] int pop_front(int head) noexcept
[[nodiscard]] int pop_front(accessor_type list) noexcept
{
if (head >= 0) {
int old_head = head;
head = items[head].next;
if (list.head >= 0) {
int old_head = list.head;
list.head = items[list.head].next;
items[old_head].id = 0u;
items[old_head].next = free_head;
free_head = old_head;
}
return head;
return list;
}
void erase_after(int elem) noexcept
......@@ -101,17 +188,18 @@ struct flat_forward_list
}
template<typename Predicate>
[[nodiscard]] int remove_if(int head, Predicate predicate) noexcept
[[nodiscard]] int remove_if(accessor_type list,
Predicate predicate) noexcept
{
while (head >= 0 && predicate(items[head].id))
head = pop_front(head);
while (list.head >= 0 && predicate(items[list.head].id))
list.head = pop_front(list.head);
if (head < 0)
return head;
if (list.head < 0)
return list.head;
int current = head;
int next = items[head].next;
int current = list.head;
int next = items[list.head].next;
while (current >= 0 && next >= 0) {
if (predicate(items[next].id)) {
......@@ -122,29 +210,31 @@ struct flat_forward_list
};
}
return head;
return list;
}
[[nodiscard]] int clear(int head) noexcept
[[nodiscard]] int clear(accessor_type list) noexcept
{
while (head >= 0)
head = pop_front(head);
while (list.head >= 0)
list.head = pop_front(list.head);
return -1;
return list;
}
};
template<typename T>
struct flat_list
{
static_assert(std::is_trivial<T>::value &&
std::is_standard_layout<T>::value,
"flat_list needs trivial type");
struct accessor_type
{
int head = -1;
int tail = -1;
};
static_assert(std::is_trivial<T>::value, "flat_list needs trivial type");
struct item
{
T id;
......@@ -152,6 +242,110 @@ struct flat_list
int next;
};
struct iterator
{
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
using reference = T&;
item* items = nullptr;
accessor_type list;
iterator(flat_list<T>& self, int pos)
: items(self.items_)
, list(list_)
{}
iterator() = default;
iterator(const iterator&) = default;
iterator(iterator&&) = default;
iterator operator=(const iterator&) = default;
iterator operator=(iterator&&) = default;
void forward()
{
if (pos >= 0)
pos = items[pos].next;
}
void backward()
{
if (pos >= 0)
pos = items[pos].previous;
}
iterator operator++(int)
{
if (pos < 0)
return iterator(items, -1);
iterator copy(*this);
forward();
return copy;
}
iterator& operator++()
{
forward();
return *this;
}
iterator operator--(int)
{
if (pos < 0)
return iterator(items, -1);
iterator copy(*this);
backward();
return copy;
}
iterator& operator--()
{
backward();
return *this;
}
const pointer operator->() const
{
return &items[pos].id;
}
reference operator*() const
{
return items[pos].id;
}
friend void swap(iterator& lhs, iterator& rhs)
{
auto items_ = lhs.items;
auto id_ = lhs.id;
lhs.items = rhs.items;
lhs.id = rhs.id;
rhs.items = items_;
rhs.id = id_;
}
friend bool operator==(const iterator& lhs, const iterator& rhs)
{
return lhs.id == rhs.id;
}
friend bool operator!=(const iterator& lhs, const iterator& rhs)
{
return !(lhs.id == rhs.id);
}
};
item* items = nullptr;
int size = 0;
int free_head = -1;
......@@ -308,10 +502,10 @@ struct flat_list
return list;
while (list.head >= 0 && predicate(items[list.head].id))
list = pop_front();
list = pop_front(list);
while (list.tail >= 0 && predicate(items[list.tail].id))
list = pop_back();
list = pop_back(list);
for (int current = list.head; current != list.tail;
current = items[current].next) {
......
/*
* This file is part of VLE, a framework for multi-modeling, simulation
* and analysis of complex dynamical systems.
* https://www.vle-project.org
*
* Copyright (c) 2003-2018 Gauthier Quesnel <gauthier.quesnel@inra.fr>
* Copyright (c) 2003-2018 ULCO http://www.univ-littoral.fr
* Copyright (c) 2007-2018 INRA http://www.inra.fr
*
* See the AUTHORS or Authors.txt file for copyright owners and
* contributors
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef ORG_VLEPROJECT_BITS_VECTOR_HPP
#define ORG_VLEPROJECT_BITS_VECTOR_HPP
#include <memory>
#include <type_traits>
namespace bits {
template<typename T>
struct vector
{
static_assert(std::is_trivial<T>() == true);
// using this_type = vector<T>;
// using value_type = T;