- Fixed some variable naming with graph and it's PrettyPrinter

- Added boost-atomic and boost-thread as dependencies for concurrency support
This commit is contained in:
2025-08-21 06:44:22 -04:00
parent fe4c49d092
commit ff27caab4f
22 changed files with 235 additions and 275 deletions

6
.gitmodules vendored
View File

@@ -1,3 +1,9 @@
[submodule "external/cpptrace"]
path = external/cpptrace
url = https://github.com/jeremy-rifkin/cpptrace.git
[submodule "external/boost-atomic"]
path = external/boost-atomic
url = https://github.com/boostorg/atomic
[submodule "external/boost-thread"]
path = external/boost-thread
url = https://github.com/boostorg/thread

View File

@@ -20,9 +20,9 @@ cmake_minimum_required(VERSION 3.30)
project(fennec)
# External dependencies should be loaded here
# CppTrace is a dependency of the project, added as a git submodule
add_subdirectory(external/cpptrace)
add_subdirectory(external/boost-atomic)
add_subdirectory(external/boost-thread)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_C_STANDARD 23)
@@ -138,11 +138,6 @@ add_library(fennec STATIC
include/fennec/memory/detail/_ptr_traits.h
# CONCURRENCY ==========================================================================================================
include/fennec/concurrency/thread.h
include/fennec/concurrency/mutex.h
include/fennec/concurrency/atomic.h
# DEBUG ================================================================================================================
source/debug/assert_impl.cpp
@@ -223,8 +218,11 @@ target_link_options(fennec PRIVATE ${FENNEC_PRIVATE_LINK_OPTIONS}) # Do not comp
# This implementation is designed to be as readable as possible, and expose information that would otherwise be obfuscated
target_link_libraries(fennec PRIVATE
cpptrace::cpptrace
${FENNEC_LINK_LIBRARIES}
cpptrace::cpptrace
Boost::atomic
Boost::thread
)

1
external/boost-atomic vendored Submodule

Submodule external/boost-atomic added at 8a6de6d93d

1
external/boost-thread vendored Submodule

Submodule external/boost-thread added at a1f89c9518

View File

@@ -396,10 +396,10 @@ class GraphPrinter:
class Iterator:
def __init__(self, val):
self.node_pool = val['_node_pool']['_table']['_alloc']['_data']
self.max_nodes = val['_node_pool']['_table']['_alloc']['_capacity']
self.conn_map = val['_conn_map']['_alloc']['_data']
self.max_conn = val['_conn_map']['_size']
self.node_pool = val['_vertex_pool']['_table']['_alloc']['_data']
self.max_nodes = val['_vertex_pool']['_table']['_alloc']['_capacity']
self.conn_map = val['_edge_map']['_alloc']['_data']
self.max_conn = val['_edge_map']['_size']
self.index = 0
def __iter__(self):
@@ -447,7 +447,7 @@ class GraphPrinter:
def __init__(self, val):
self.val = val
self.size = val['_node_pool']['_size']
self.size = val['_vertex_pool']['_size']
def to_string(self):
if self.size == 0:

View File

@@ -1,22 +0,0 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// 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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_CONCURRENCY_ATOMIC_H
#define FENNEC_CONCURRENCY_ATOMIC_H
#endif // FENNEC_CONCURRENCY_ATOMIC_H

View File

@@ -1,22 +0,0 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// 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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_CONCURRENCY_MUTEX_H
#define FENNEC_CONCURRENCY_MUTEX_H
#endif // FENNEC_CONCURRENCY_MUTEX_H

View File

@@ -1,22 +0,0 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// 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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_CONCURRENCY_THREAD_H
#define FENNEC_CONCURRENCY_THREAD_H
#endif // FENNEC_CONCURRENCY_THREAD_H

View File

@@ -149,7 +149,7 @@ public:
///
/// \returns The number of edges in the graph
constexpr size_t num_edges() const {
return _conn_pool.size();
return _edge_pool.size();
}
///
@@ -170,7 +170,7 @@ public:
/// \param b The second vertex
/// \returns `true` if the edge exists, `false` otherwise
constexpr bool exists(size_t a, size_t b) const {
return _conn_map[a][b] != nullptr;
return _edge_map[a][b] != nullptr;
}
///
@@ -189,8 +189,8 @@ public:
/// \param b The second vertex
/// \returns `true` if both edges exist, `false` otherwise
constexpr bool is_undirected(size_t a, size_t b) const {
const auto* e0 = _conn_map[a][b];
const auto* e1 = _conn_map[b][a];
const auto* e0 = _edge_map[a][b];
const auto* e1 = _edge_map[b][a];
if (not (e0 != nullptr && e1 != nullptr)) {
return false;
}
@@ -232,9 +232,9 @@ public:
if (empty()) {
return nullptr;
}
edge_t* it = _conn_map[a][b];
edge_t* it = _edge_map[a][b];
if (it) {
return _conn_pool[*it];
return _edge_pool[*it];
}
return nullptr;
}
@@ -248,9 +248,9 @@ public:
if (empty()) {
return nullptr;
}
const edge_t* it = _conn_map[a][b];
const edge_t* it = _edge_map[a][b];
if (it) {
return _conn_pool[*it];
return _edge_pool[*it];
}
return nullptr;
}
@@ -261,10 +261,10 @@ public:
/// \returns A list containing all vertices `x` with edges from `vertex` to `x...`
list<size_t> outgoing(size_t vertex) {
list<size_t> res;
if (empty() || vertex >= _conn_map.size()) {
if (empty() || vertex >= _edge_map.size()) {
return res;
}
for (const auto& it : _conn_map[vertex]) {
for (const auto& it : _edge_map[vertex]) {
res.push_back(it.first);
}
return res;
@@ -276,11 +276,11 @@ public:
/// \returns A list containing all vertices `x` with edges from `x...` to `vertex`
list<size_t> incoming(size_t vertex) {
list<size_t> res;
if (empty() || vertex >= _conn_map.size()) {
if (empty() || vertex >= _edge_map.size()) {
return res;
}
for (size_t n = 0; n < _conn_map.size(); ++n) {
if (_conn_map[n][vertex]) {
for (size_t n = 0; n < _edge_map.size(); ++n) {
if (_edge_map[n][vertex]) {
res.push_back(n);
}
}
@@ -293,11 +293,11 @@ public:
/// \returns A list containing all vertices `x` that have symmetric edges with `vertex`
list<size_t> symmetric(size_t vertex) {
list<size_t> res;
if (empty() || vertex >= _conn_map.size()) {
if (empty() || vertex >= _edge_map.size()) {
return res;
}
for (const auto& it : _conn_map[vertex]) {
if (_conn_map[it.first][vertex]) {
for (const auto& it : _edge_map[vertex]) {
if (_edge_map[it.first][vertex]) {
res.push_back(it.first);
}
}
@@ -314,11 +314,11 @@ public:
/// \returns A list containing all vertices `x` that have symmetric edges with `vertex`
list<size_t> undirected(size_t vertex) {
list<size_t> res;
if (empty() || vertex >= _conn_map.size()) {
if (empty() || vertex >= _edge_map.size()) {
return res;
}
for (const auto& it : _conn_map[vertex]) {
const auto* at = _conn_map[it.first][vertex];
for (const auto& it : _edge_map[vertex]) {
const auto* at = _edge_map[it.first][vertex];
if (at != nullptr && *at == it.second) {
res.push_back(it.first);
}
@@ -332,10 +332,10 @@ public:
/// \param vertex The id of the vertex
/// \returns A pointer to a map containing edges mapped from this vertex
const auto* edges(size_t vertex) {
if (empty() || vertex >= _conn_map.size()) {
if (empty() || vertex >= _edge_map.size()) {
return nullptr;
}
return &_conn_map[vertex];
return &_edge_map[vertex];
}
/// @}
@@ -392,19 +392,19 @@ public:
return;
}
if (_conn_map.size() < _vertex_pool.capacity()) {
_conn_map.resize(_vertex_pool.capacity());
if (_edge_map.size() < _vertex_pool.capacity()) {
_edge_map.resize(_vertex_pool.capacity());
}
auto it = _conn_map[a][b];
auto it = _edge_map[a][b];
size_t conn;
if (it != nullptr) {
conn = *it;
_conn_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
_edge_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
} else {
conn = _conn_pool.emplace(fennec::forward<ArgsT>(args)...);
conn = _edge_pool.emplace(fennec::forward<ArgsT>(args)...);
}
_conn_map[a].emplace(b, conn);
_edge_map[a].emplace(b, conn);
}
///
@@ -419,21 +419,21 @@ public:
return;
}
if (_conn_map.size() < _vertex_pool.capacity()) {
_conn_map.resize(_vertex_pool.capacity());
if (_edge_map.size() < _vertex_pool.capacity()) {
_edge_map.resize(_vertex_pool.capacity());
}
auto it = _conn_map[a][b];
auto it = _edge_map[a][b];
size_t conn;
if (it != nullptr) {
conn = *it;
_conn_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
_edge_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
} else {
conn = _conn_pool.emplace(fennec::forward<ArgsT>(args)...);
conn = _edge_pool.emplace(fennec::forward<ArgsT>(args)...);
}
_conn_map[a].emplace(b, conn);
_conn_map[b].emplace(a, conn);
_edge_map[a].emplace(b, conn);
_edge_map[b].emplace(a, conn);
}
///
@@ -443,20 +443,20 @@ public:
constexpr void cut_edge(size_t a, size_t b) {
// Find the edge object
const auto* it = _conn_map[a][b];
const auto* it = _edge_map[a][b];
if (not it) {
return;
}
size_t c = *it;
// Check if undirected
const auto* at = _conn_map[b][a];
const auto* at = _edge_map[b][a];
if (not at || *at != c) {
_conn_pool.erase(c);
_edge_pool.erase(c);
}
// Erase the edge mapping
_conn_map[a].erase(b);
_edge_map[a].erase(b);
}
///
@@ -464,15 +464,15 @@ public:
/// \param a The first vertex id
/// \param b The second vertex id
constexpr void cut_edge2(size_t a, size_t b) {
const auto* ita = _conn_map[a][b];
const auto* itb = _conn_map[a][b];
const auto* ita = _edge_map[a][b];
const auto* itb = _edge_map[a][b];
if (not (ita || itb)) {
return;
}
if (ita) _conn_pool.erase(*ita);
if (itb) _conn_pool.erase(*itb);
_conn_map[a].erase(b);
_conn_map[b].erase(a);
if (ita) _edge_pool.erase(*ita);
if (itb) _edge_pool.erase(*itb);
_edge_map[a].erase(b);
_edge_map[b].erase(a);
}
///
@@ -491,8 +491,8 @@ public:
/// \brief Clear the graph, destructing all vertices and edges.
void clear() {
_vertex_pool.clear();
_conn_pool.clear();
_conn_map.clear();
_edge_pool.clear();
_edge_map.clear();
}
/// @}
@@ -503,8 +503,8 @@ public:
private:
vertex_pool_t _vertex_pool;
edge_pool_t _conn_pool;
edge_map_t _conn_map;
edge_pool_t _edge_pool;
edge_map_t _edge_map;
template<typename...ArgsT>
size_t _insert(ArgsT&&...args) {

View File

@@ -47,6 +47,23 @@ configurability and programmability within those systems and their stages. This
be achieved using events at different stages of those engines that are on-demand.
## External Libraries
* `cpptrace`
* Walking the stack and retrieving information about the code is *very* platform
dependent, and it makes little sense spending days writing a library that will
be less effective.
* `boost-atomic` `boost-thread`
* Concurrency support is *extremely* platform dependent. Each OS has its own
implementations with its own idiosyncrasies. We are not writing an operating system,
we do not want to spend days writing a library that will be less performant and
much more bugprone. Comparing this with the containers library, the containers
library is worth reimplementing since it is not platform dependent and we can
make an implementation with consistent behavior. Boost is slightly better for our
purposes since its implementation is more consistent across implementations than
the C++ stdlib.
## Definitions
&ensp; Many subpages of these documents will contain tables that use symbols to
@@ -62,4 +79,7 @@ denote implementation and testing progress. The symbols are defined below.
## Libraries
- [C++ Language Library](./CPP_LANGUAGE.md#c-language-library-lang)
- [Platform Support Library](./PLATFORM_SUPPORT.md#platform--api-support)
- [Platform Support Library](./PLATFORM_SUPPORT.md#platform-support-library-platform)
- [Memory Library](./MEMORY.md#memory-library-memory)
- [Containers Library](./CONTAINERS.md#containers-library-containers)
- [Language Processing Library](./LANGUAGE_PROCESSING.md#language-processing-library-langproc)

View File

@@ -59,22 +59,22 @@ See:
| is_null_pointer | ✅ | ✅ |
| is_integral | ✅ | ✅ |
| is_floating_point | ✅ | ✅ |
| is_array | ✅ | |
| is_array | ✅ | 🚧 |
| is_enum | ⛔ | ⛔ |
| is_union | ⛔ | ⛔ |
| is_class | ✅ | ✅ |
| is_function | ⛔ | ⛔ |
| is_pointer | ✅ | ✅ |
| is_lvalue_reference | ✅ | ✅ |
| is_rvalue_reference | | |
| is_rvalue_reference | | |
| is_member_object_pointer | ⛔ | ⛔ |
| is_member_function_pointer | ⛔ | ⛔ |
### Composite Types
| Symbol | Implemented | Passed |
|:------------------|:-----------:|:------:|
| is_fundamental | | |
| is_arithmetic | | |
| is_fundamental | | |
| is_arithmetic | | |
| is_scalar | ⛔ | ⛔ |
| is_object | ⛔ | ⛔ |
| is_compound | ⛔ | ⛔ |
@@ -84,9 +84,9 @@ See:
### Type Properties
| Symbol | Implemented | Passed |
|:----------------------------------|:-----------:|:------:|
| is_const | | |
| is_volatile | | |
| is_trivially_copyable | | |
| is_const | | |
| is_volatile | | |
| is_trivially_copyable | | |
| is_standard_layout | ⛔ | ⛔ |
| has_unique_object_representations | ⛔ | ⛔ |
| is_empty | ⛔ | ⛔ |
@@ -95,8 +95,8 @@ See:
| is_final | ⛔ | ⛔ |
| is_aggregate | ⛔ | ⛔ |
| is_implicit_lifetime | ⛔ | ⛔ |
| is_signed | | |
| is_unsigned | | |
| is_signed | | |
| is_unsigned | | |
| is_bounded_array | ⛔ | ⛔ |
| is_unbounded_array | ⛔ | ⛔ |
| is_scoped_enum | ⛔ | ⛔ |
@@ -104,16 +104,16 @@ See:
### Supported Operations
| Symbol | Implemented | Passed |
|:------------------------------------|:-----------:|:------:|
| is_constructible | | |
| is_trivially_constructible | | |
| is_constructible | | |
| is_trivially_constructible | | |
| is_nothrow_constructible | ⛔ | ⛔ |
| is_default_constructible | | |
| is_default_constructible | | |
| is_trivially_default_constructible | ⛔ | ⛔ |
| is_nothrow_default_constructible | ⛔ | ⛔ |
| is_copy_constructible | | |
| is_copy_constructible | | |
| is_trivially_copy_constructible | ⛔ | ⛔ |
| is_nothrow_copy_constructible | ⛔ | ⛔ |
| is_move_constructible | | |
| is_move_constructible | | |
| is_trivially_move_constructible | ⛔ | ⛔ |
| is_nothrow_move_constructible | ⛔ | ⛔ |
| is_destructible | ⛔ | ⛔ |
@@ -137,10 +137,10 @@ See:
### Type Relationships
| Symbol | Implemented | Passed |
|:------------------------------------|:-----------:|:------:|
| is_same | | |
| is_same | | |
| is_base_of | ❌ | ❌ |
| is_virtual_base_of | ❌ | ❌ |
| is_convertible | | |
| is_convertible | | |
| is_nothrow_convertible | ❌ | ❌ |
| is_layout_compatible | ❌ | ❌ |
| is_pointer_interconvertible_base_of | ❌ | ❌ |
@@ -152,19 +152,19 @@ See:
### Type Transformations
| Symbol | Implemented | Passed |
|:---------------------|:-----------:|:------:|
| add_const | | |
| add_volatile | | |
| add_cv | | |
| remove_const | | |
| remove_volatile | | |
| remove_cv | | |
| add_lvalue_reference | | |
| add_rvalue_reference | | |
| remove_reference | | |
| add_pointer | | |
| remove_pointer | | |
| make_signed | | |
| make_unsigned | | |
| add_const | | |
| add_volatile | | |
| add_cv | | |
| remove_const | | |
| remove_volatile | | |
| remove_cv | | |
| add_lvalue_reference | | |
| add_rvalue_reference | | |
| remove_reference | | |
| add_pointer | | |
| remove_pointer | | |
| make_signed | | |
| make_unsigned | | |
| remove_extent | ❌ | ❌ |
| remove_all_extents | ❌ | ❌ |
@@ -175,16 +175,16 @@ See:
| aligned_union | ❌ | ❌ |
| aligned_union | ❌ | ❌ |
| decay | 🚧 | 🚧 |
| remove_cvref | | |
| enable_if | | |
| conditional | | |
| remove_cvref | | |
| enable_if | | |
| conditional | | |
| common_type | ❌ | ❌ |
| common_reference | ❌ | ❌ |
| basic_common_reference | ❌ | ❌ |
| underlying_type | ❌ | ❌ |
| result_of | ❌ | ❌ |
| invoke_result | ❌ | ❌ |
| void_t | | |
| void_t | | |
### Logical Operations
| Symbol | Implemented | Passed |
@@ -196,9 +196,9 @@ See:
### Sequences
| Symbol | Implemented | Passed |
|:-------------------------------------------------|:-----------:|:------:|
| const_sequence | | |
| const_integer_sequence (`std::integer_sequence`) | | |
| make_integer_sequence | | |
| const_index_sequence (`std::index_sequence`) | | |
| make_index_sequence | | |
| concat_sequence | | |
| const_sequence | | |
| const_integer_sequence (`std::integer_sequence`) | | |
| make_integer_sequence | | |
| const_index_sequence (`std::index_sequence`) | | |
| make_index_sequence | | |
| concat_sequence | | |