Browse Source

fixed code to make it clear and stable

Ivan Arkhipov 6 years ago
parent
commit
4b108623a7
3 changed files with 201 additions and 191 deletions
  1. 7 11
      StackAllocator.h
  2. 149 169
      XorList.h
  3. 45 11
      main.cpp

+ 7 - 11
StackAllocator.h

@@ -9,7 +9,7 @@
 #include <c++/new>
 #include <memory.h>
 
-template<typename T, int elements_in_block = 100>
+template<typename T, size_t elements_in_block = 128256>
 class StackAllocator {
 
 public:
@@ -28,11 +28,11 @@ public:
 
     StackAllocator() : last_block_(nullptr) {}
 
+
     StackAllocator(const StackAllocator &other) : last_block_(nullptr) {};
 
-    StackAllocator(StackAllocator &&other) noexcept : last_block_(nullptr) {
-        other.last_block_ = nullptr;
-    }
+    template<class U>
+    explicit StackAllocator(const StackAllocator<U> &other) : last_block_(nullptr) {};
 
     ~StackAllocator() {
         for (Block *block = last_block_; block != nullptr;) {
@@ -43,12 +43,8 @@ public:
     }
 
     pointer allocate(size_type n, const void * = nullptr) {
-        if (n > elements_in_block) {
-            throw std::bad_alloc();
-        }
-
         if (!last_block_ || last_block_->end_ + n >= last_block_->block_end_) {
-            last_block_ = new Block(last_block_);
+            last_block_ = new Block(std::max(n, elements_in_block), last_block_);
         }
         pointer result = last_block_->end_;
         last_block_->end_ += n;
@@ -75,8 +71,8 @@ private:
         Block() {}
 
     public:
-        explicit Block(Block *prev_block = nullptr) {
-            begin_ = reinterpret_cast<pointer>(::operator new(sizeof(value_type) * elements_in_block));
+        explicit Block(int els_in_block = elements_in_block, Block *prev_block = nullptr) {
+            begin_ = reinterpret_cast<pointer>(::operator new(sizeof(value_type) * els_in_block));
             end_ = begin_;
             block_end_ = begin_ + elements_in_block;
             prev_block_ = prev_block;

+ 149 - 169
XorList.h

@@ -12,18 +12,21 @@
 #include <list>
 #include <memory>
 #include <utility>
+#include <iostream>
+#include <stdexcept>
 
 template<typename T>
 struct XorListNode {
 public:
     XorListNode() = delete;
 
-    XorListNode(const T &val) {
+    explicit XorListNode(const T &val) {
         val_ = val;
     }
 
-    XorListNode(const T &&val) {
-        val_ = std::forward<XorListNode<T> >(val);
+    explicit XorListNode(T &&val) {
+        val_ = std::move(val);//std::forward<T>(val);
+        //std::cout << "move-constructor\n";
     }
 
     XorListNode *right(const XorListNode *left) const {
@@ -59,7 +62,6 @@ struct FwdXorListIterator {
 
     FwdXorListIterator(Node *x, Node *prev) : node_(x), left_(prev) {}
 
-    // Must downcast from _List_node_base to _List_node to get to value.
     reference operator*() const {
         return node_->val_;
     }
@@ -115,16 +117,21 @@ template<typename T, typename Allocator = std::allocator<T> >
 class XorList {
 
 private:
-    typedef typename Allocator::template rebind<XorListNode<T>>::other allocator_type;
-    typedef __gnu_cxx::__alloc_traits<allocator_type> Allocator_traits;
+
+    typedef typename __gnu_cxx::__alloc_traits<Allocator>::template
+    rebind<T>::other T_alloc_type;
+    typedef __gnu_cxx::__alloc_traits<T_alloc_type> T_alloc_traits;
+
+    typedef typename T_alloc_traits::template rebind<XorListNode<T> >::other Node_alloc_type;
+    typedef __gnu_cxx::__alloc_traits<Node_alloc_type> Node_alloc_traits;
 
 public:
     // types:
     typedef T value_type;
-    typedef typename Allocator_traits::pointer pointer;
-    typedef typename Allocator_traits::const_pointer const_pointer;
-    typedef value_type& reference;
-    typedef const value_type& const_reference;
+    typedef typename T_alloc_traits::pointer pointer;
+    typedef typename T_alloc_traits::const_pointer const_pointer;
+    typedef value_type &reference;
+    typedef const value_type &const_reference;
 
     typedef FwdXorListIterator<T> iterator;
     typedef std::reverse_iterator<iterator> reverse_iterator;
@@ -133,249 +140,222 @@ public:
     //typedef Allocator                                  allocator_type;
 
     explicit XorList(const Allocator &alloc = Allocator())
-            : front_(nullptr), back_(nullptr), size_(0), allocator_(allocator_type()) {}
+            : front_(nullptr), back_(nullptr), size_(0), allocator_(Node_alloc_type(alloc)) {}
 
-    XorList(size_type count, const_reference value = T(), const Allocator &alloc = Allocator())
-            : front_(nullptr), back_(nullptr), size_(0), allocator_(allocator_type()) {
+    explicit XorList(size_type count, const_reference value = T(), const Allocator &alloc = Allocator())
+            : front_(nullptr), back_(nullptr), size_(0), allocator_(Node_alloc_type(alloc)) {
         for (size_type i = 0; i < count; i++)
             push_back(value);
     }
 
-    XorList(const XorList &other) {
-        *this = other;
-    }
+    XorList &operator=(const XorList &other) {
+        if (this == &other)
+            return *this;
 
-    XorList(const XorList &&other) noexcept {
-        *this = other;
-    }
+        clear();
 
-    ~XorList() {
-        XorListNode<T> *xleft = nullptr;
-        XorListNode<T> *x = front_;
-        while (x != back_) {
-            XorListNode<T> *xnext = x->right(xleft);
-            if (xnext) {
-                allocator_.destroy(xleft);
-                allocator_.deallocate(xleft, 1);
-            }
-            xleft = x;
-            x = xnext;
-        }
+        allocator_ = Node_alloc_type(other.allocator_);
+        front_ = back_  = nullptr;
+        size_ = 0;
 
-        if (xleft) {
-            allocator_.destroy(xleft);
-            allocator_.deallocate(xleft, 1);
-        }
-        if (x) {
-            allocator_.destroy(x);
-            allocator_.deallocate(x, 1);
-        }
+        for (const auto& i: other)
+            push_back(i);
+        std::cout << "Copy assignment\n";
+        return *this;
     }
 
-    XorList &operator=(const XorList &other) {
+    XorList &operator=(XorList &&other) noexcept {
         if (this == &other)
             return *this;
 
-        this->~XorList();
+        clear();
+
         this->front_ = other.front_;
         this->back_ = other.back_;
         this->size_ = other.size_;
-        this->allocator_ = other.allocator_;
+        this->allocator_ = std::move(other.allocator_);
+
+        other.front_ = other.back_ = nullptr;
+        other.size_ = 0;
+
+        std::cout << "Move assignment\n";
+        return *this;
     }
 
-    XorList &operator=(const XorList &&other) noexcept {
-        if (this == &other)
-            return *this;
+    ~XorList() {
+        clear();
+    }
 
-        this->~XorList();
-        this->front_ = other.front_;
-        this->back_ = other.back_;
-        this->size_ = other.size_;
-        this->allocator_ = other.allocator_;
+    template <typename xorlist_t>
+    explicit XorList(xorlist_t &&other) noexcept : XorList() {
+        *this = std::forward<xorlist_t>(other);
     }
 
-    value_type front() {
+    value_type front() const {
         return front_->val_;
     }
 
-    value_type back() {
+    value_type back() const {
         return back_->val_;
     }
 
-    iterator begin() {
+    iterator begin() const {
         return iterator(front_, nullptr);
     }
 
-    iterator end() {
+    iterator end() const {
         if (!back_)
             return iterator(nullptr, nullptr);
         return ++iterator(back_, back_->left(nullptr));
     }
 
-    reverse_iterator rbegin() {
+    reverse_iterator rbegin() const {
         return reverse_iterator(front_, nullptr);
     }
 
-    reverse_iterator rend() {
+    reverse_iterator rend() const {
         return ++reverse_iterator(back_, back_->left(nullptr));
     }
 
-    size_type size() {
+    size_type size() const {
         return size_;
     }
 
-    void push_back(const value_type &val) {
-        XorListNode<T> *past_back = back_;
-        back_ = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
-        allocator_.construct(back_, std::forward<XorListNode<T> >(val));
-        back_->assign_leftright(past_back, nullptr);
-        if (past_back)
-            past_back->assign_leftright(past_back->left(nullptr), back_);
-        if (!front_)
-            front_ = back_;
-        size_++;
+    template<typename v_type>
+    void push_back(v_type &&val) {
+        insert_after(iterator(back_, back_ ? back_->left(nullptr) : nullptr), std::forward<v_type>(val));
     }
 
-    void push_back(const value_type &&val) {
-        XorListNode<value_type> *past_back = back_;
-        back_ = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
-        allocator_.construct(back_, XorListNode<T>(std::forward<XorListNode<T> >(val)));
-        back_->assign_leftright(past_back, nullptr);
-        if (past_back)
-            past_back->assign_leftright(past_back->left(nullptr), back_);
-        if (!front_)
-            front_ = back_;
-        size_++;
+    template<typename v_type>
+    void push_front(v_type &&val) {
+        insert_before(iterator(front_, nullptr), std::forward<v_type>(val));
     }
 
-    void push_front(const value_type &val) {
-        XorListNode<value_type> *past_front = front_;
-        front_ = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
-        allocator_.construct(front_, std::forward<XorListNode<T> >(val));
-        front_->assign_leftright(nullptr, past_front);
-        if (past_front)
-            past_front->assign_leftright(front_, past_front->right(nullptr));
-        if (!back_)
-            back_ = front_;
-        size_++;
+    template<typename v_type>
+    void insert_before(iterator it, v_type &&val) {
+        _m_insert(it, std::forward<v_type>(val), BEFORE);
     }
 
-    void push_front(const value_type &&val) {
-        XorListNode<value_type> *past_front = front_;
-        front_ = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
-        allocator_.construct(front_, std::forward<XorListNode<T> >(val));
-        front_->assign_leftright(nullptr, past_front);
-        if (past_front)
-            past_front->assign_leftright(front_,  past_front->right(nullptr));
-        if (!back_)
-            back_ = front_;
-        size_++;
+    template<typename v_type>
+    void insert_after(iterator it, v_type &&val) {
+        _m_insert(it, std::forward<v_type>(val), AFTER);
     }
 
     void pop_back() {
-        XorListNode<T> *past_back = back_;
-        back_ = back_->left(nullptr);
-        back_->assign_leftright(back_->left(past_back), nullptr);
-        allocator_.destroy(past_back);
-        allocator_.deallocate(past_back, 1);
+        if (!back_)
+            return;
+        erase(iterator(back_, back_->left(nullptr)));
     }
 
     void pop_front() {
-        XorListNode<T> *past_front = front_;
-        front_ = front_->right(nullptr);
-        front_->assign_leftright(nullptr, front_->right(past_front));
-        allocator_.destroy(past_front);
-        allocator_.deallocate(past_front, 1);
+        if (!front_)
+            return;
+        erase(iterator(front_, nullptr));
     }
 
-    void insert_before(iterator it, T &val) {
-        XorListNode<T> *cur = *it;
-        XorListNode<T> *prev = it.left_;
-        XorListNode<T> *past = it.node_->right(prev);
-
-        XorListNode<T> *new_node = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
-        allocator_.construct(new_node, std::forward<XorListNode<T> >(val));
-        new_node->assign_leftright(prev, cur);
+    void erase(iterator it) {
+        XorListNode<T> *left = it.left_;
+        XorListNode<T> *cur = it.node_;
+        XorListNode<T> *right = it.node_->right(left);
 
-        if (cur)
-            cur->assign_leftright(new_node, past);
+        if (left)
+            left->assign_leftright(left->left(cur), right);
 
-        if (prev)
-            prev->assign_leftright(prev->left(cur), new_node);
-    }
+        if (right)
+            right->assign_leftright(left, right->right(cur));
 
-    void insert_before(iterator it, T &&val) {
-        XorListNode<T> *cur = *it;
-        XorListNode<T> *prev = it.left_;
-        XorListNode<T> *past = it.node_->right(prev);
+        if (cur) {
+            size_--;
+            if (front_ == cur)
+                front_ = cur->right(nullptr);
+            if (back_ == cur)
+                back_ = cur->left(nullptr);
+        }
 
-        XorListNode<T> *new_node = allocator_.allocate(1);
-        allocator_.construct(new_node, std::forward<XorListNode<T> >(val));
-        new_node->assign_leftright(prev, cur);
+        allocator_.destroy(cur);
+        allocator_.deallocate(cur, 1);
+    }
 
-        if (cur)
-            cur->assign_leftright(new_node, past);
+    void clear() {
+        XorListNode<T> *xleft = nullptr;
+        XorListNode<T> *x = front_;
+        while (x != back_) {
+            XorListNode<T> *xnext = x->right(xleft);
+            if (xnext) {
+                allocator_.destroy(xleft);
+                allocator_.deallocate(xleft, 1);
+            }
+            xleft = x;
+            x = xnext;
+        }
 
-        if (prev)
-            prev->assign_leftright(prev->left(cur), new_node);
+        if (xleft) {
+            allocator_.destroy(xleft);
+            allocator_.deallocate(xleft, 1);
+        }
+        if (x) {
+            allocator_.destroy(x);
+            allocator_.deallocate(x, 1);
+        }
+        size_ = 0;
+        front_ = back_ = nullptr;
     }
 
-    void insert_after(iterator it, T &val) {
-        XorListNode<T> *cur = *it;
-        XorListNode<T> *prev = it.left_;
-        XorListNode<T> *past = it.node_->right(prev);
-
-        XorListNode<T> *new_node = allocator_.allocate(1);
-        allocator_.construct(new_node, std::forward<XorListNode<T> >(val));
-        new_node->assign_leftright(cur, past);
+private:
+    enum E_POSITION_TYPE {
+        BEFORE,
+        AFTER
+    };
 
-        if (cur)
-            cur->assign_leftright(prev, new_node);
+    template<typename v_type>
+    void _m_insert(iterator it, v_type &&val, E_POSITION_TYPE pos) {
+        XorListNode<T> *cur = it.node_;
+        XorListNode<T> *left = it.left_;
 
-        if (past)
-            past->assign_leftright(new_node, past->right(cur));
-    }
+        XorListNode<T> *new_node = reinterpret_cast<XorListNode<T> *>(allocator_.allocate(1));
+        Node_alloc_traits::construct(allocator_, new_node, std::forward<v_type>(val));
+        new_node->assign_leftright(nullptr, nullptr);
 
-    void insert_after(iterator it, T &&val) {
-        XorListNode<T> *cur = *it;
-        XorListNode<T> *prev = it.left_;
-        XorListNode<T> *past = it.node_->right(prev);
+        if (!front_ || !back_) {
+            front_ = back_ = new_node;
+            size_ = 1;
+            return;
+        }
 
-        XorListNode<T> *new_node = allocator_.allocate(1);
-        allocator_.construct(new_node, std::forward<XorListNode<T> >(val));
-        new_node->assign_leftright(cur, past);
+        XorListNode<T> *right = it.node_->right(left);
 
-        if (cur)
-            cur->assign_leftright(prev, new_node);
 
-        if (past)
-            past->assign_leftright(new_node, past->right(cur));
-    }
+        if (pos == BEFORE) {
+            new_node->assign_leftright(left, cur);
+            cur->assign_leftright(new_node, right);
 
-    void erase(iterator it) {
-        XorListNode<T> *prev = it.left_;
-        XorListNode<T> *cur = it.operator->();
-        XorListNode<T> *past = it.node_->right(prev);
+            if (left)
+                left->assign_leftright(left->left(cur), new_node);
 
-        if (prev)
-            prev->assign_leftright(prev->left(cur), past);
+            if (cur == front_)
+                front_ = new_node;
+        }
 
-        if (past)
-            past->assign_leftright(prev, past->right(cur));
+        if (pos == AFTER) {
+            new_node->assign_leftright(cur, right);
+            cur->assign_leftright(left, new_node);
 
-        if (cur)
-            size_--;
+            if (right)
+                right->assign_leftright(new_node, right->right(cur));
 
-        allocator_.destroy(cur);
-        allocator_.deallocate(cur, 1);
+            if (cur == back_)
+                back_ = new_node;
+        }
+        size_++;
     }
 
+
 private:
     XorListNode<T> *front_;
     XorListNode<T> *back_; // Pointer to the LAST element
 
     size_type size_;
-    allocator_type allocator_;
+    Node_alloc_type allocator_;
 
 };
 

+ 45 - 11
main.cpp

@@ -9,9 +9,19 @@
 #include "StackAllocator.h"
 #include "XorList.h"
 
-const int NUM_CONTENT = 10000000;
+const int NUM_CONTENT = 20;
 int random_nums[NUM_CONTENT * 2];
+//
+//class A{
+//    A() {
+//        int f = 5, g = 0;
+//        f / g
+//    }
+//    int a[1000000];
+//};
+
 
+#include <list>
 int main() {
     std::random_device rd;
     std::mt19937 mt(rd());
@@ -21,9 +31,9 @@ int main() {
         random_nums[i] = random_gen(mt);
     }
 
-//    for (const auto &i : random_nums)
-//        std::cout << i << " ";
-//    std::cout << "\n\n";
+    for (const auto &i : random_nums)
+        std::cout << i << " ";
+    std::cout << "\n\n";
 
     {
         std::list<int> b;
@@ -44,18 +54,19 @@ int main() {
         std::clock_t end_std_allocator = std::clock();
         std::cout << "Time for std::list with std::allocator is "
                   << (end_std_allocator - start_std_allocator) / (double) (CLOCKS_PER_SEC / 1000) << "ms" << std::endl;
-//
-//        std::cout << "=============DATA BEGIN===========\n";
-//        for (auto k = b.begin(); k != b.end(); ++k)
-//            std::cout << *k << " ";
-//        std::cout << "\n==============DATA END============\n\n";
+
+        std::cout << "=============DATA BEGIN===========\n";
+        for (auto k = b.begin(); k != b.end(); ++k)
+            std::cout << *k << " ";
+        std::cout << "\n==============DATA END============\n\n";
     }
 
     {
         XorList<int, StackAllocator<int>> a;
         std::clock_t start_stack_allocator = std::clock();
         for (int i = 0; i < NUM_CONTENT * 2; i += 2) {
-            a.push_front(random_nums[i]);
+            const int val = random_nums[i];
+            a.push_front(val);
             if (a.front() != random_nums[i]) {
                 std::cout << "AAAAAAAAAAAAAAAA: front is  " << a.front() << ", expected: " << random_nums[i]
                           << std::endl;
@@ -71,11 +82,34 @@ int main() {
         std::cout << "Time for XorList with StackAllocator is "
                   << (end_stack_allocator - start_stack_allocator) / (double) (CLOCKS_PER_SEC / 1000) << "ms"
                   << std::endl;
+
+        std::cout << "final size = " << a.size() << "\n";
+        int size = a.size();
+
+        for (int i = 0; i < size / 2; i++) {
+            std::cout << "back = " << a.back() << std::endl;
+            a.pop_back();
+        }
+
+        std::cout << "final size = " << a.size() << "\n";
+        XorList<int, StackAllocator<int>> c;
+        c = XorList<int, StackAllocator<int>>();
+        c = a;
+        std::cout << "=============DATA BEGIN===========\n";
+        for (auto k = c.begin(); k != c.end(); ++k)
+            std::cout << *k << " ";
+        std::cout << "\n==============DATA END============\n\n";
+    }
+
+
 //
+//    XorList<int, StackAllocator<int>> a;
+//    for (int i = 0; i < 50; i++) {
+//        a.push_back(rand());
+//    }
 //        std::cout << "=============DATA BEGIN===========\n";
 //        for (auto k = a.begin(); k != a.end(); ++k)
 //            std::cout << *k << " ";
 //        std::cout << "\n==============DATA END============\n\n";
-    }
     return 0;
 }