Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 99 additions & 71 deletions task01/isok.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
// �Ȝ�� ��ѳ����ҙ� ��������ҙ� ��ӳ��ܖ� ��ߙ��.
// ���� Ә�ș ������� ��ٔ�ۙ� ��� ����-���ȳ�, �� �ٚ ����� ȣ�� �ȓ��� TIME_KEEPER. �����ȣ������, ������ TimeKeeper.h ܘ��� Ә�ș ��ӳҙ� �� ������
// https://gist.github.com/wardencliffe/164128a000c1625b5d0f097f6d5df455
// �����ۙ� ߘ��-��Әƿ � ��ѳ��ۙ� ј�� � ���٘��, �� � �ӕ�� ��� � ��� ��ܚ���. :)

#include <type_traits>
#include <cstdio>

//#define TIME_KEEPER 1

#include <vector>

#ifdef TIME_KEEPER
# include "../../TimeKeeper.h"
#endif
#include <cstdint>


#define MIN(a, b) ((a) < (b) ? (a) : (b))
Expand All @@ -24,6 +12,7 @@
// Declaration
////////////////////////////////////////////////////////////////


template<typename T>
class myvector
{
Expand Down Expand Up @@ -65,21 +54,25 @@ class myvector

void resize_internal(int new_size);

void free_data();
void clean_stack_data();

private:

T m_buffer_stack[BUFFER_STACK_SIZE];
uint8_t m_buffer_stack[BUFFER_STACK_SIZE * ELEMENT_SIZE];
T * m_data_stack = reinterpret_cast<T *>(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;

T m_empty_element = T();
};


////////////////////////////////////////////////////////////////
// Definition
////////////////////////////////////////////////////////////////


template <typename T>
myvector<T>::myvector()
{
Expand All @@ -89,8 +82,7 @@ myvector<T>::myvector()
template <typename T>
myvector<T>::~myvector()
{
if (m_data != m_buffer_stack)
delete[] m_data;
clear();
}

template <typename T>
Expand All @@ -109,84 +101,85 @@ template <typename T>
void myvector<T>::add(const T & value)
{
check_before_add(1);
m_data[m_size] = value;
new (&m_data[m_size]) T(value);
++m_size;
}

template <typename T>
T& myvector<T>::add()
{
check_before_add(1);
m_data[m_size] = m_empty_element;
++m_size;
return m_data[m_size - 1];
}

template <typename T>
void myvector<T>::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]);
m_data[index].~T();
if (index < m_size - 1)
{
// Not last element erased so we should move tail of a vector
memmove(m_data + index, m_data + index + 1, (m_size - index - 1) * ELEMENT_SIZE);
}
--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 <typename T>
void myvector<T>::push_back(const T& value)
void myvector<T>::push_back(const T & value)
{
add(value);
}

template <typename T>
void myvector<T>::erase(const T* item)
void myvector<T>::erase(const T * item)
{
erase(item - m_data);
erase(static_cast<int>(item - m_data));
}

template <typename T>
T& myvector<T>::operator[](int index)
T & myvector<T>::operator[](int index)
{
return *(m_data + CLAMP(index, 0, m_capacity - 1));
}

template <typename T>
const T& myvector<T>::operator[](int index) const
const T & myvector<T>::operator[](int index) const
{
return *(m_data + CLAMP(index, 0, m_capacity - 1));
}

template <typename T>
T* myvector<T>::begin()
T * myvector<T>::begin()
{
return m_data;
}

template <typename T>
T* myvector<T>::end()
T * myvector<T>::end()
{
return m_data + m_size;
}

template <typename T>
void myvector<T>::clear()
{
if (m_data != m_buffer_stack)
if (m_data != m_data_stack)
{
delete[] m_data;
m_data = m_buffer_stack;
free_data();
m_data = m_data_stack;
m_capacity = BUFFER_STACK_SIZE;
}

if (!IS_POD)
else
{
for (int i = 0; i < BUFFER_STACK_SIZE; ++i)
m_data[i] = m_empty_element;
clean_stack_data();
}

m_size = 0;
}

Expand All @@ -195,18 +188,26 @@ void myvector<T>::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[i] = m_empty_element;
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;
}
Expand All @@ -221,15 +222,15 @@ void myvector<T>::reserve(int min_capacity)
template <typename T>
void myvector<T>::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 <typename T>
void myvector<T>::check_after_remove()
{
if (m_size * 4 < m_capacity)
resize_internal(m_size + 1);
resize_internal(m_size);
}

template <typename T>
Expand All @@ -238,10 +239,10 @@ void myvector<T>::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 = 128;
int chosen_size = BUFFER_STACK_SIZE * 4;
float factor = 4.0f;
while (chosen_size - 1 < new_size)
{
Expand All @@ -259,42 +260,69 @@ void myvector<T>::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)
if (m_data != m_data_stack)
{
delete[] m_data;
m_data = m_buffer_stack;
free_data();
m_data = m_data_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_data_stack)
{
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)
*dst_data = *src_data;
}
// Create new memory
new_data = reinterpret_cast<T *>(malloc(chosen_size * ELEMENT_SIZE));
need_to_copy = true;
}
if (m_data != m_buffer_stack)
else
{
delete[] m_data;
// Try to reallocate memory
new_data = reinterpret_cast<T *>(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<T *>(malloc(chosen_size * ELEMENT_SIZE));
need_to_copy = true;
}
}
else if (!IS_POD)
if (need_to_copy)
{
for (int i = 0; i < copy_size; ++i)
m_data[i] = m_empty_element;
int copy_size = chosen_size < m_size ? chosen_size : m_size;
if (copy_size > 0)
memcpy(new_data, m_data, copy_size * ELEMENT_SIZE);
if (m_data == m_data_stack)
clean_stack_data();
else
free_data();
}
m_data = new_data;
m_capacity = chosen_size;
}
}

template <typename T>
void myvector<T>::free_data()
{
if (!IS_POD)
{
for (int i = 0; i < m_size; ++i)
m_data[i].~T();
}
free(m_data);
}

template <typename T>
void myvector<T>::clean_stack_data()
{
if (!IS_POD)
{
for (int i = 0; i < BUFFER_STACK_SIZE && i < m_size; ++i)
m_data[i].~T();
}
}