From 7b7906daa37ef1c2c41efdc68cbfdd66b9af2021 Mon Sep 17 00:00:00 2001 From: Igor Sokolov Date: Sun, 9 Apr 2017 11:22:27 +0700 Subject: [PATCH 1/4] Fixed some bugs in myvector class. --- task01/isok.h | 77 +++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/task01/isok.h b/task01/isok.h index 5611af5..f2df248 100644 --- a/task01/isok.h +++ b/task01/isok.h @@ -1,19 +1,6 @@ -// Ȝ ѳҙ ҙ ӳܖ ߙ. -// Әș ٔۙ -ȳ, ٚ ȣ ȓ TIME_KEEPER. ȣ, TimeKeeper.h ܘ Әș ӳҙ -// https://gist.github.com/wardencliffe/164128a000c1625b5d0f097f6d5df455 -// ۙ ߘ-Әƿ ѳۙ ј ٘, ӕ ܚ. :) - #include #include -//#define TIME_KEEPER 1 - -#include - -#ifdef TIME_KEEPER -# include "../../TimeKeeper.h" -#endif - #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) @@ -24,6 +11,7 @@ // Declaration //////////////////////////////////////////////////////////////// + template class myvector { @@ -72,14 +60,14 @@ class myvector T * m_data = m_buffer_stack; int m_size = 0; int m_capacity = BUFFER_STACK_SIZE; - - T m_empty_element = T(); }; + //////////////////////////////////////////////////////////////// // Definition //////////////////////////////////////////////////////////////// + template myvector::myvector() { @@ -89,8 +77,7 @@ myvector::myvector() template myvector::~myvector() { - if (m_data != m_buffer_stack) - delete[] m_data; + clear(); } template @@ -109,7 +96,7 @@ template void myvector::add(const T & value) { check_before_add(1); - m_data[m_size] = value; + new (&m_data[m_size]) T(value); ++m_size; } @@ -117,7 +104,6 @@ template T& myvector::add() { check_before_add(1); - m_data[m_size] = m_empty_element; ++m_size; return m_data[m_size - 1]; } @@ -125,48 +111,61 @@ T& myvector::add() template void myvector::erase(int index) { - if (index < m_size) + if (index >= 0 && index < m_size) { - while (++index < m_size) - m_data[index - 1] = std::move_if_noexcept(m_data[index]); + if (index < m_size - 1) + { + // Not last element erased so we should move tail of a vector + if (IS_POD) + { + memmove(m_data + index, m_data + index + 1, (m_size - index - 1) * ELEMENT_SIZE); + } + else + { + m_data[index].~T(); + while (++index < m_size) + new (&m_data[index - 1]) T(std::move_if_noexcept(m_data[index])); + } + } --m_size; - m_data[m_size] = m_empty_element; - check_after_remove(); + m_data[m_size].~T(); // probably required if no move semantics supported + // Disabled for now because adds some a little overhead + //check_after_remove(); } } template -void myvector::push_back(const T& value) +void myvector::push_back(const T & value) { add(value); } template -void myvector::erase(const T* item) +void myvector::erase(const T * item) { erase(item - m_data); } template -T& myvector::operator[](int index) +T & myvector::operator[](int index) { return *(m_data + CLAMP(index, 0, m_capacity - 1)); } template -const T& myvector::operator[](int index) const +const T & myvector::operator[](int index) const { return *(m_data + CLAMP(index, 0, m_capacity - 1)); } template -T* myvector::begin() +T * myvector::begin() { return m_data; } template -T* myvector::end() +T * myvector::end() { return m_data + m_size; } @@ -180,11 +179,10 @@ void myvector::clear() m_data = m_buffer_stack; m_capacity = BUFFER_STACK_SIZE; } - - if (!IS_POD) + else if (!IS_POD) { for (int i = 0; i < BUFFER_STACK_SIZE; ++i) - m_data[i] = m_empty_element; + m_data[m_size].~T(); } m_size = 0; @@ -198,13 +196,13 @@ void myvector::resize(int new_size) if (!IS_POD) { for (int i = new_size; i < m_size; ++i) - m_data[i] = m_empty_element; + m_data[m_size].~T(); } } else if (new_size > m_size) { resize_internal(new_size); - + if (IS_POD) memset(m_data + m_size, 0, (new_size - m_size) * ELEMENT_SIZE); } @@ -259,12 +257,13 @@ void myvector::resize_internal(int new_size) if (chosen_size == m_capacity) return; - if (chosen_size < BUFFER_STACK_SIZE) + if (chosen_size <= BUFFER_STACK_SIZE) { if (m_data != m_buffer_stack) { delete[] m_data; m_data = m_buffer_stack; + m_capacity = BUFFER_STACK_SIZE; } } else @@ -282,7 +281,7 @@ void myvector::resize_internal(int new_size) T * src_data = m_data; T * dst_data = new_data; for (int i = 0; i < copy_size; ++i, ++src_data, ++dst_data) - *dst_data = *src_data; + new (dst_data) T(std::move_if_noexcept(*src_data)); } } if (m_data != m_buffer_stack) @@ -291,8 +290,8 @@ void myvector::resize_internal(int new_size) } else if (!IS_POD) { - for (int i = 0; i < copy_size; ++i) - m_data[i] = m_empty_element; + for (int i = 0; i < BUFFER_STACK_SIZE; ++i) + m_data[m_size].~T(); } m_data = new_data; m_capacity = chosen_size; From be9e0f8aac825555b039c0c355ea34d857ba0d1c Mon Sep 17 00:00:00 2001 From: Igor Sokolov Date: Sun, 9 Apr 2017 12:23:21 +0700 Subject: [PATCH 2/4] Moved to realloc implementation. --- task01/isok.h | 117 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 83 insertions(+), 34 deletions(-) diff --git a/task01/isok.h b/task01/isok.h index f2df248..48c6c81 100644 --- a/task01/isok.h +++ b/task01/isok.h @@ -53,6 +53,9 @@ class myvector void resize_internal(int new_size); + void free_data(); + void clean_stack_data(); + private: T m_buffer_stack[BUFFER_STACK_SIZE]; @@ -113,6 +116,7 @@ void myvector::erase(int index) { if (index >= 0 && index < m_size) { + m_data[index].~T(); if (index < m_size - 1) { // Not last element erased so we should move tail of a vector @@ -122,7 +126,6 @@ void myvector::erase(int index) } else { - m_data[index].~T(); while (++index < m_size) new (&m_data[index - 1]) T(std::move_if_noexcept(m_data[index])); } @@ -175,16 +178,11 @@ void myvector::clear() { if (m_data != m_buffer_stack) { - delete[] m_data; + free_data(); m_data = m_buffer_stack; m_capacity = BUFFER_STACK_SIZE; } - else if (!IS_POD) - { - for (int i = 0; i < BUFFER_STACK_SIZE; ++i) - m_data[m_size].~T(); - } - + clean_stack_data(); m_size = 0; } @@ -193,18 +191,26 @@ void myvector::resize(int new_size) { if (new_size < m_size) { + // Remove elements if (!IS_POD) { for (int i = new_size; i < m_size; ++i) - m_data[m_size].~T(); + m_data[i].~T(); } } else if (new_size > m_size) { + // Add elements resize_internal(new_size); - if (IS_POD) + { memset(m_data + m_size, 0, (new_size - m_size) * ELEMENT_SIZE); + } + else + { + for (int i = m_size; i < new_size; ++i) + new (&m_data[i]) T(); + } } m_size = new_size; } @@ -219,15 +225,15 @@ void myvector::reserve(int min_capacity) template void myvector::check_before_add(int count) { - if (m_size + 1 + count > m_capacity) - resize_internal(m_size + 1 + count); + if (m_size + count > m_capacity) + resize_internal(m_size + count); } template void myvector::check_after_remove() { if (m_size * 4 < m_capacity) - resize_internal(m_size + 1); + resize_internal(m_size); } template @@ -236,10 +242,10 @@ void myvector::resize_internal(int new_size) static const float min_factor = 1.2f; static const float factor_step = 0.2f; - if (m_data == m_buffer_stack && new_size < BUFFER_STACK_SIZE) + if (m_data == m_buffer_stack && new_size <= BUFFER_STACK_SIZE) return; - int chosen_size = 128; + int chosen_size = BUFFER_STACK_SIZE * 4; float factor = 4.0f; while (chosen_size - 1 < new_size) { @@ -261,39 +267,82 @@ void myvector::resize_internal(int new_size) { if (m_data != m_buffer_stack) { - delete[] m_data; + free_data(); m_data = m_buffer_stack; m_capacity = BUFFER_STACK_SIZE; } } else { - T * new_data = new T[chosen_size]; - int copy_size = chosen_size < m_size ? chosen_size : m_size; - if (copy_size > 0) + bool need_to_copy = false; + T * new_data = nullptr; + if (m_data == m_buffer_stack) { - if (IS_POD) + // Create new memory + new_data = reinterpret_cast(malloc(chosen_size * ELEMENT_SIZE)); + need_to_copy = true; + } + else + { + // Try to reallocate memory + new_data = reinterpret_cast(realloc(m_data, chosen_size * ELEMENT_SIZE)); + + // This can be failed so we should check this and workaround + if (!new_data) + { + new_data = reinterpret_cast(malloc(chosen_size * ELEMENT_SIZE)); + need_to_copy = true; + } + } + if (need_to_copy) + { + int copy_size = chosen_size < m_size ? chosen_size : m_size; + if (copy_size > 0) + { + if (IS_POD) + { + memcpy(new_data, m_data, copy_size * ELEMENT_SIZE); + } + else + { + T * src_data = m_data; + T * dst_data = new_data; + for (int i = 0; i < copy_size; ++i, ++src_data, ++dst_data) + new (dst_data) T(std::move_if_noexcept(*src_data)); + } + } + if (m_data == m_buffer_stack) { - memcpy(new_data, m_data, copy_size * ELEMENT_SIZE); + // Clean buffer stack + clean_stack_data(); } else { - T * src_data = m_data; - T * dst_data = new_data; - for (int i = 0; i < copy_size; ++i, ++src_data, ++dst_data) - new (dst_data) T(std::move_if_noexcept(*src_data)); + free_data(); } } - if (m_data != m_buffer_stack) - { - delete[] m_data; - } - else if (!IS_POD) - { - for (int i = 0; i < BUFFER_STACK_SIZE; ++i) - m_data[m_size].~T(); - } m_data = new_data; m_capacity = chosen_size; } } + +template +void myvector::free_data() +{ + if (!IS_POD) + { + for (int i = 0; i < m_size; ++i) + m_data[i].~T(); + } + free(m_data); +} + +template +void myvector::clean_stack_data() +{ + if (!IS_POD) + { + for (int i = 0; i < BUFFER_STACK_SIZE; ++i) + m_data[i].~T(); + } +} From 6fc83449e2636a365cdbaf61a049f7511e070c7c Mon Sep 17 00:00:00 2001 From: Igor Sokolov Date: Sun, 9 Apr 2017 12:38:29 +0700 Subject: [PATCH 3/4] Some more fixes. --- task01/isok.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/task01/isok.h b/task01/isok.h index 48c6c81..441b0f1 100644 --- a/task01/isok.h +++ b/task01/isok.h @@ -1,5 +1,6 @@ #include #include +#include #define MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -58,9 +59,10 @@ class myvector private: - T m_buffer_stack[BUFFER_STACK_SIZE]; + uint8_t m_buffer_stack[BUFFER_STACK_SIZE * ELEMENT_SIZE]; + T * m_data_stack = reinterpret_cast(m_buffer_stack); - T * m_data = m_buffer_stack; + T * m_data = m_data_stack; int m_size = 0; int m_capacity = BUFFER_STACK_SIZE; }; @@ -176,13 +178,16 @@ T * myvector::end() template void myvector::clear() { - if (m_data != m_buffer_stack) + if (m_data != m_data_stack) { free_data(); - m_data = m_buffer_stack; + m_data = m_data_stack; m_capacity = BUFFER_STACK_SIZE; } - clean_stack_data(); + else + { + clean_stack_data(); + } m_size = 0; } @@ -242,7 +247,7 @@ void myvector::resize_internal(int new_size) static const float min_factor = 1.2f; static const float factor_step = 0.2f; - if (m_data == m_buffer_stack && new_size <= BUFFER_STACK_SIZE) + if (m_data == m_data_stack && new_size <= BUFFER_STACK_SIZE) return; int chosen_size = BUFFER_STACK_SIZE * 4; @@ -265,10 +270,10 @@ void myvector::resize_internal(int new_size) if (chosen_size <= BUFFER_STACK_SIZE) { - if (m_data != m_buffer_stack) + if (m_data != m_data_stack) { free_data(); - m_data = m_buffer_stack; + m_data = m_data_stack; m_capacity = BUFFER_STACK_SIZE; } } @@ -276,7 +281,7 @@ void myvector::resize_internal(int new_size) { bool need_to_copy = false; T * new_data = nullptr; - if (m_data == m_buffer_stack) + if (m_data == m_data_stack) { // Create new memory new_data = reinterpret_cast(malloc(chosen_size * ELEMENT_SIZE)); @@ -311,15 +316,10 @@ void myvector::resize_internal(int new_size) new (dst_data) T(std::move_if_noexcept(*src_data)); } } - if (m_data == m_buffer_stack) - { - // Clean buffer stack + if (m_data == m_data_stack) clean_stack_data(); - } else - { free_data(); - } } m_data = new_data; m_capacity = chosen_size; @@ -342,7 +342,7 @@ void myvector::clean_stack_data() { if (!IS_POD) { - for (int i = 0; i < BUFFER_STACK_SIZE; ++i) + for (int i = 0; i < BUFFER_STACK_SIZE && i < m_size; ++i) m_data[i].~T(); } } From babce66e7dfd98a82f578d5166da4e8edba9f50e Mon Sep 17 00:00:00 2001 From: Igor Sokolov Date: Mon, 10 Apr 2017 04:26:14 +0700 Subject: [PATCH 4/4] Some more optimization. --- task01/isok.h | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/task01/isok.h b/task01/isok.h index 441b0f1..7b2d6e9 100644 --- a/task01/isok.h +++ b/task01/isok.h @@ -122,15 +122,7 @@ void myvector::erase(int index) if (index < m_size - 1) { // Not last element erased so we should move tail of a vector - if (IS_POD) - { - memmove(m_data + index, m_data + index + 1, (m_size - index - 1) * ELEMENT_SIZE); - } - else - { - while (++index < m_size) - new (&m_data[index - 1]) T(std::move_if_noexcept(m_data[index])); - } + memmove(m_data + index, m_data + index + 1, (m_size - index - 1) * ELEMENT_SIZE); } --m_size; m_data[m_size].~T(); // probably required if no move semantics supported @@ -148,7 +140,7 @@ void myvector::push_back(const T & value) template void myvector::erase(const T * item) { - erase(item - m_data); + erase(static_cast(item - m_data)); } template @@ -303,19 +295,7 @@ void myvector::resize_internal(int new_size) { int copy_size = chosen_size < m_size ? chosen_size : m_size; if (copy_size > 0) - { - if (IS_POD) - { - memcpy(new_data, m_data, copy_size * ELEMENT_SIZE); - } - else - { - T * src_data = m_data; - T * dst_data = new_data; - for (int i = 0; i < copy_size; ++i, ++src_data, ++dst_data) - new (dst_data) T(std::move_if_noexcept(*src_data)); - } - } + memcpy(new_data, m_data, copy_size * ELEMENT_SIZE); if (m_data == m_data_stack) clean_stack_data(); else