Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Arraylist, fast new container to add front and back #1677

Merged
merged 6 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions src/pch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "utils/definitions.hpp"
#include "utils/simd.hpp"
#include "utils/vectorset.hpp"
#include "utils/arraylist.hpp"
#include "utils/vectorsort.hpp"

// --------------------
Expand Down
158 changes: 158 additions & 0 deletions src/utils/arraylist.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/**
* Canary - A free and open-source MMORPG server emulator
* Copyright (©) 2019-2022 OpenTibiaBR <[email protected]>
* Repository: https://github.com/opentibiabr/canary
* License: https://github.com/opentibiabr/canary/blob/main/LICENSE
* Contributors: https://github.com/opentibiabr/canary/graphs/contributors
* Website: https://docs.opentibiabr.com/
*/

#pragma once

#include <algorithm>
#include <vector>

// # Mehah
// Arraylist is a very fast container for adding to the front and back,
// it uses two vectors to do this juggling and doesn't allow you to remove the front, as it is slow,
// use std::list for this case.

namespace stdext {
template <typename T>
class arraylist {
public:
bool contains(const T &v) {
update();
return std::ranges::find(backContainer, v) != backContainer.end();
}

bool erase(const T &v) {
update();

const auto &it = std::ranges::find(backContainer, v);
if (it == backContainer.end()) {
return false;
}
backContainer.erase(it);

return true;
}

bool erase(const size_t begin, const size_t end) {
update();

if (begin > size() || end > size()) {
return false;
}

backContainer.erase(backContainer.begin() + begin, backContainer.begin() + end);
return true;
}

template <class F>
bool erase_if(F fnc) {
update();
return std::erase_if(backContainer, std::move(fnc)) > 0;
}

auto &front() {
update();
return backContainer.front();
}

void pop_back() {
update();
backContainer.pop_back();
}

auto &back() {
update();
return backContainer.back();
}

void push_front(const T &v) {
needUpdate = true;
frontContainer.push_back(v);
}

void push_front(T &&_Val) {
needUpdate = true;
frontContainer.push_back(std::move(_Val));
}

template <class... _Valty>
decltype(auto) emplace_front(_Valty &&... v) {
needUpdate = true;
return frontContainer.emplace_back(std::forward<_Valty>(v)...);
}

void push_back(const T &v) {
backContainer.push_back(v);
}

void push_back(T &&_Val) {
backContainer.push_back(std::move(_Val));
}

template <class... _Valty>
decltype(auto) emplace_back(_Valty &&... v) {
return backContainer.emplace_back(std::forward<_Valty>(v)...);
}

bool empty() const noexcept {
return backContainer.empty() && frontContainer.empty();
}

size_t size() const noexcept {
return backContainer.size() + frontContainer.size();
}

auto begin() noexcept {
update();
return backContainer.begin();
}

auto end() noexcept {
return backContainer.end();
}

void clear() noexcept {
frontContainer.clear();
return backContainer.clear();
}

void reserve(size_t newCap) noexcept {
backContainer.reserve(newCap);
frontContainer.reserve(newCap);
}

const auto &data() noexcept {
update();
return backContainer.data();
}

T &operator[](const size_t i) {
update();
return backContainer[i];
}

private:
inline void update() noexcept {
if (!needUpdate) {
return;
}

needUpdate = false;
std::ranges::reverse(frontContainer);
frontContainer.insert(frontContainer.end(), make_move_iterator(backContainer.begin()), make_move_iterator(backContainer.end()));
backContainer.clear();
backContainer.insert(backContainer.end(), make_move_iterator(frontContainer.begin()), make_move_iterator(frontContainer.end()));
frontContainer.clear();
}

std::vector<T> backContainer;
std::vector<T> frontContainer;

bool needUpdate = false;
};
}
1 change: 1 addition & 0 deletions vcproj/canary.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@
<ClInclude Include="..\src\server\server.hpp" />
<ClInclude Include="..\src\server\server_definitions.hpp" />
<ClInclude Include="..\src\server\signals.hpp" />
<ClInclude Include="..\src\utils\arraylist.hpp" />
<ClInclude Include="..\src\utils\benchmark.hpp" />
<ClInclude Include="..\src\utils\const.hpp" />
<ClInclude Include="..\src\utils\definitions.hpp" />
Expand Down