- Started setting up a thread safe window manager
- Created thread & atomic structures
This commit is contained in:
@@ -16,13 +16,13 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
# ======================================================================================================================
|
# ======================================================================================================================
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.28)
|
cmake_minimum_required(VERSION 3.28...3.31)
|
||||||
|
|
||||||
project(fennec)
|
project(fennec)
|
||||||
set(FENNEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
set(FENNEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
macro(fennec_add_sources)
|
macro(fennec_add_sources)
|
||||||
list(APPEND FENNEC_EXTRA_SOURCES ${ARGN})
|
list(APPEND FENNEC_SOURCES ${ARGN})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
macro(fennec_add_definitions)
|
macro(fennec_add_definitions)
|
||||||
@@ -37,6 +37,10 @@ macro(fennec_add_shared_libraries)
|
|||||||
list(APPEND FENNEC_SHARED_LIBRARIES ${ARGN})
|
list(APPEND FENNEC_SHARED_LIBRARIES ${ARGN})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
macro(fennec_add_compile_options)
|
||||||
|
list(APPEND FENNEC_PRIVATE_COMPILE_OPTIONS ${ARGN})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
macro(fennec_add_link_options)
|
macro(fennec_add_link_options)
|
||||||
list(APPEND FENNEC_PRIVATE_LINK_OPTIONS ${ARGN})
|
list(APPEND FENNEC_PRIVATE_LINK_OPTIONS ${ARGN})
|
||||||
endmacro()
|
endmacro()
|
||||||
@@ -76,12 +80,9 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME}
|
|||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME})
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME})
|
||||||
|
|
||||||
# add the test suite as a sub-project
|
# Core Files
|
||||||
add_subdirectory(test)
|
fennec_add_sources(
|
||||||
|
# CORE =================================================================================================================
|
||||||
add_library(fennec STATIC
|
|
||||||
|
|
||||||
# CORE =================================================================================================================
|
|
||||||
include/fennec/core/engine.h source/core/engine.cpp
|
include/fennec/core/engine.h source/core/engine.cpp
|
||||||
include/fennec/core/event.h source/core/event.cpp
|
include/fennec/core/event.h source/core/event.cpp
|
||||||
include/fennec/core/logger.h source/core/logger.cpp
|
include/fennec/core/logger.h source/core/logger.cpp
|
||||||
@@ -90,7 +91,7 @@ add_library(fennec STATIC
|
|||||||
include/fennec/core/system.h
|
include/fennec/core/system.h
|
||||||
|
|
||||||
|
|
||||||
# SCENE ================================================================================================================
|
# SCENE ================================================================================================================
|
||||||
include/fennec/scene/scene.h source/scene/scene.cpp
|
include/fennec/scene/scene.h source/scene/scene.cpp
|
||||||
include/fennec/scene/component.h
|
include/fennec/scene/component.h
|
||||||
include/fennec/scene/scene_node.h
|
include/fennec/scene/scene_node.h
|
||||||
@@ -99,7 +100,7 @@ add_library(fennec STATIC
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# RENDERERS ============================================================================================================
|
# RENDERERS ============================================================================================================
|
||||||
include/fennec/renderers/interface/forward.h
|
include/fennec/renderers/interface/forward.h
|
||||||
|
|
||||||
include/fennec/renderers/interface/gfxcontext.h
|
include/fennec/renderers/interface/gfxcontext.h
|
||||||
@@ -107,7 +108,7 @@ add_library(fennec STATIC
|
|||||||
include/fennec/renderers/interface/gfxresourcepool.h
|
include/fennec/renderers/interface/gfxresourcepool.h
|
||||||
|
|
||||||
|
|
||||||
# CONTAINERS ===========================================================================================================
|
# CONTAINERS ===========================================================================================================
|
||||||
include/fennec/containers/containers.h
|
include/fennec/containers/containers.h
|
||||||
|
|
||||||
include/fennec/containers/array.h
|
include/fennec/containers/array.h
|
||||||
@@ -135,7 +136,7 @@ add_library(fennec STATIC
|
|||||||
include/fennec/containers/detail/_tuple.h
|
include/fennec/containers/detail/_tuple.h
|
||||||
|
|
||||||
|
|
||||||
# lang =================================================================================================================
|
# lang =================================================================================================================
|
||||||
include/fennec/lang/lang.h
|
include/fennec/lang/lang.h
|
||||||
include/fennec/lang/metaprogramming.h
|
include/fennec/lang/metaprogramming.h
|
||||||
|
|
||||||
@@ -172,7 +173,7 @@ add_library(fennec STATIC
|
|||||||
include/fennec/lang/detail/_type_sequences.h
|
include/fennec/lang/detail/_type_sequences.h
|
||||||
|
|
||||||
|
|
||||||
# RTTI =================================================================================================================
|
# RTTI =================================================================================================================
|
||||||
include/fennec/rtti/typeid.h
|
include/fennec/rtti/typeid.h
|
||||||
include/fennec/rtti/type_data.h
|
include/fennec/rtti/type_data.h
|
||||||
include/fennec/rtti/type.h
|
include/fennec/rtti/type.h
|
||||||
@@ -189,7 +190,7 @@ add_library(fennec STATIC
|
|||||||
include/fennec/rtti/detail/_type_name.h
|
include/fennec/rtti/detail/_type_name.h
|
||||||
|
|
||||||
|
|
||||||
# MEMORY ===============================================================================================================
|
# MEMORY ===============================================================================================================
|
||||||
include/fennec/memory/new.h source/memory/new.cpp
|
include/fennec/memory/new.h source/memory/new.cpp
|
||||||
|
|
||||||
include/fennec/memory/allocator.h
|
include/fennec/memory/allocator.h
|
||||||
@@ -201,11 +202,11 @@ add_library(fennec STATIC
|
|||||||
|
|
||||||
include/fennec/memory/detail/_ptr_traits.h
|
include/fennec/memory/detail/_ptr_traits.h
|
||||||
|
|
||||||
# DEBUG ================================================================================================================
|
# DEBUG ================================================================================================================
|
||||||
source/debug/assert_impl.cpp
|
source/debug/assert_impl.cpp
|
||||||
|
|
||||||
|
|
||||||
# MATH =================================================================================================================
|
# MATH =================================================================================================================
|
||||||
include/fennec/math/math.h
|
include/fennec/math/math.h
|
||||||
|
|
||||||
include/fennec/math/scalar.h
|
include/fennec/math/scalar.h
|
||||||
@@ -230,6 +231,7 @@ add_library(fennec STATIC
|
|||||||
include/fennec/math/ext/constants.h
|
include/fennec/math/ext/constants.h
|
||||||
include/fennec/math/ext/primes.h
|
include/fennec/math/ext/primes.h
|
||||||
include/fennec/math/ext/quaternion.h
|
include/fennec/math/ext/quaternion.h
|
||||||
|
include/fennec/math/ext/rect.h
|
||||||
include/fennec/math/ext/transform.h
|
include/fennec/math/ext/transform.h
|
||||||
|
|
||||||
|
|
||||||
@@ -241,7 +243,7 @@ add_library(fennec STATIC
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# string ===============================================================================================================
|
# string ===============================================================================================================
|
||||||
include/fennec/string/locale.h
|
include/fennec/string/locale.h
|
||||||
include/fennec/string/cstring.h
|
include/fennec/string/cstring.h
|
||||||
include/fennec/string/string.h
|
include/fennec/string/string.h
|
||||||
@@ -250,7 +252,7 @@ add_library(fennec STATIC
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# format ===============================================================================================================
|
# format ===============================================================================================================
|
||||||
include/fennec/format/format.h
|
include/fennec/format/format.h
|
||||||
include/fennec/format/format_arg.h
|
include/fennec/format/format_arg.h
|
||||||
include/fennec/format/formatter.h
|
include/fennec/format/formatter.h
|
||||||
@@ -262,46 +264,55 @@ add_library(fennec STATIC
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# filesystem ===========================================================================================================
|
# filesystem ===========================================================================================================
|
||||||
include/fennec/filesystem/file.h source/filesystem/file.cpp
|
include/fennec/filesystem/file.h source/filesystem/file.cpp
|
||||||
include/fennec/filesystem/path.h source/filesystem/path.cpp
|
include/fennec/filesystem/path.h source/filesystem/path.cpp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# interpret ============================================================================================================
|
# interpret ============================================================================================================
|
||||||
include/fennec/interpret/tokenizer.h
|
include/fennec/interpret/tokenizer.h
|
||||||
|
|
||||||
|
|
||||||
# PLATFORM =============================================================================================================
|
# PLATFORM =============================================================================================================
|
||||||
|
|
||||||
include/fennec/platform/interface/fwd.h
|
include/fennec/platform/interface/fwd.h
|
||||||
include/fennec/platform/interface/display_server.h
|
include/fennec/platform/interface/display_server.h
|
||||||
include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp
|
include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp
|
||||||
include/fennec/platform/interface/window.h source/platform/interface/window.cpp
|
include/fennec/platform/interface/window.h source/platform/interface/window.cpp
|
||||||
|
|
||||||
# GRAPHICS =============================================================================================================
|
# GRAPHICS =============================================================================================================
|
||||||
|
|
||||||
include/fennec/gfx3d/mesh_instance.h
|
include/fennec/gfx3d/mesh_instance.h
|
||||||
|
)
|
||||||
|
|
||||||
# EXTRA SOURCES ========================================================================================================
|
# add the test suite as a sub-project
|
||||||
|
add_subdirectory(test)
|
||||||
|
|
||||||
${FENNEC_EXTRA_SOURCES}
|
add_library(fennec STATIC
|
||||||
include/fennec/math/ext/rect.h
|
${FENNEC_SOURCES}
|
||||||
include/fennec/platform/opengl/egl/error.h
|
|
||||||
include/fennec/platform/window_manager.h
|
include/fennec/platform/window_manager.h
|
||||||
|
include/fennec/platform/window_manager.cpp
|
||||||
|
include/fennec/platform/window_manager.h
|
||||||
|
include/fennec/lang/function.h
|
||||||
|
include/fennec/threading/thread.h
|
||||||
|
include/fennec/threading/detail/_thread.h
|
||||||
|
include/fennec/lang/detail/_function.h
|
||||||
|
include/fennec/threading/atomic.h
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_dependencies(fennec metaprogramming fennec-dependencies)
|
add_dependencies(fennec metaprogramming fennec-dependencies)
|
||||||
|
|
||||||
target_compile_definitions(fennec PUBLIC
|
target_compile_definitions(fennec PUBLIC ${FENNEC_COMPILE_DEFINITIONS})
|
||||||
${FENNEC_COMPILE_DEFINITIONS}
|
target_compile_options(fennec PRIVATE ${FENNEC_PRIVATE_COMPILE_OPTIONS})
|
||||||
)
|
|
||||||
|
|
||||||
|
# Do not compile base fennec library with c++ stdlib
|
||||||
target_link_options(fennec PRIVATE ${FENNEC_PRIVATE_LINK_OPTIONS}) # Do not compile base fennec library with c++ stdlib
|
|
||||||
# fennec does not use the C++ stdlib because it is bloated, difficult to read, and implementation defined.
|
# fennec does not use the C++ stdlib because it is bloated, difficult to read, and implementation defined.
|
||||||
# This implementation is designed to be as readable as possible, and expose information that would otherwise be obfuscated
|
# This implementation is designed to be as readable as possible, and expose information that would otherwise be obfuscated
|
||||||
|
target_link_options(fennec PRIVATE ${FENNEC_PRIVATE_LINK_OPTIONS})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
target_link_libraries(fennec PRIVATE
|
target_link_libraries(fennec PRIVATE
|
||||||
${FENNEC_LINK_LIBRARIES}
|
${FENNEC_LINK_LIBRARIES}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@
|
|||||||
|
|
||||||
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror" "-fms-extensions")
|
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror" "-fms-extensions")
|
||||||
|
|
||||||
fennec_add_link_options("-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
|
fennec_add_compile_options("-ffile-prefix-map=${FENNEC_SOURCE_DIR}=.")
|
||||||
|
|
||||||
|
fennec_add_link_options("-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates" "-pthread")
|
||||||
|
|
||||||
fennec_add_definitions(
|
fennec_add_definitions(
|
||||||
_GLIBCXX_INCLUDE_NEXT_C_HEADERS=1
|
_GLIBCXX_INCLUDE_NEXT_C_HEADERS=1
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ if(FENNEC_GRAPHICS_WANT_EGL)
|
|||||||
|
|
||||||
fennec_add_sources(
|
fennec_add_sources(
|
||||||
include/fennec/platform/opengl/egl/fwd.h
|
include/fennec/platform/opengl/egl/fwd.h
|
||||||
|
include/fennec/platform/opengl/egl/error.h
|
||||||
include/fennec/platform/opengl/egl/context.h source/platform/opengl/egl/context.cpp
|
include/fennec/platform/opengl/egl/context.h source/platform/opengl/egl/context.cpp
|
||||||
include/fennec/platform/opengl/egl/surface.h source/platform/opengl/egl/surface.cpp
|
include/fennec/platform/opengl/egl/surface.h source/platform/opengl/egl/surface.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -392,10 +392,10 @@ public:
|
|||||||
constexpr void clear() {
|
constexpr void clear() {
|
||||||
size_t i = _root;
|
size_t i = _root;
|
||||||
while (i != npos) {
|
while (i != npos) {
|
||||||
fennec::destruct(_table[i]);
|
fennec::destruct(&_table[i]);
|
||||||
i = this->_next(i);
|
i = this->_next(i);
|
||||||
}
|
}
|
||||||
_table.deallocate(_table);
|
_table.deallocate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ public:
|
|||||||
using table_t = dynarray<elem_t, AllocT>;
|
using table_t = dynarray<elem_t, AllocT>;
|
||||||
using freed_t = list<size_t, AllocT>;
|
using freed_t = list<size_t, AllocT>;
|
||||||
|
|
||||||
|
class iterator;
|
||||||
|
class const_iterator;
|
||||||
|
|
||||||
|
|
||||||
// Constructors & Destructor ===========================================================================================
|
// Constructors & Destructor ===========================================================================================
|
||||||
|
|
||||||
@@ -189,6 +192,135 @@ public:
|
|||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
// Iterator ============================================================================================================
|
||||||
|
|
||||||
|
iterator begin() {
|
||||||
|
return iterator(this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() {
|
||||||
|
return iterator(this, _size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const {
|
||||||
|
return iterator(this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const {
|
||||||
|
return iterator(this, _size);
|
||||||
|
}
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
public:
|
||||||
|
iterator(object_pool* pool, size_t start)
|
||||||
|
: pool(pool), curr(start) {
|
||||||
|
_fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator(const iterator&) = default;
|
||||||
|
iterator(iterator&&) noexcept = default;
|
||||||
|
|
||||||
|
~iterator() = default;
|
||||||
|
|
||||||
|
iterator& operator=(const iterator&) = default;
|
||||||
|
iterator& operator=(iterator&&) noexcept = default;
|
||||||
|
|
||||||
|
iterator operator++(int) {
|
||||||
|
iterator ret = *this;
|
||||||
|
++curr;
|
||||||
|
_fix();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator& operator++() {
|
||||||
|
++curr;
|
||||||
|
_fix();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t& operator*() const {
|
||||||
|
return *pool->_table[curr];
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t* operator->() const {
|
||||||
|
return *pool->_table[curr];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const iterator& it) {
|
||||||
|
return pool == it.pool and curr == it.curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const iterator& it) {
|
||||||
|
return pool != it.pool or curr != it.curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
object_pool* pool;
|
||||||
|
size_t curr;
|
||||||
|
|
||||||
|
void _fix() {
|
||||||
|
while (curr < pool->_size and not pool->_table[curr]) {
|
||||||
|
++curr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class const_iterator {
|
||||||
|
public:
|
||||||
|
const_iterator(const object_pool* pool, size_t start)
|
||||||
|
: pool(pool), curr(start) {
|
||||||
|
_fix();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator(const const_iterator&) = default;
|
||||||
|
const_iterator(const_iterator&&) noexcept = default;
|
||||||
|
|
||||||
|
~const_iterator() = default;
|
||||||
|
|
||||||
|
const_iterator& operator=(const const_iterator&) = default;
|
||||||
|
const_iterator& operator=(const_iterator&&) noexcept = default;
|
||||||
|
|
||||||
|
const_iterator operator++(int) {
|
||||||
|
const_iterator ret = *this;
|
||||||
|
++curr;
|
||||||
|
_fix();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator& operator++() {
|
||||||
|
++curr;
|
||||||
|
_fix();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_t& operator*() const {
|
||||||
|
return *pool->_table[curr];
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_t* operator->() const {
|
||||||
|
return *pool->_table[curr];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const const_iterator& it) {
|
||||||
|
return pool == it.pool and curr == it.curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const const_iterator& it) {
|
||||||
|
return pool != it.pool or curr != it.curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const object_pool* pool;
|
||||||
|
size_t curr;
|
||||||
|
|
||||||
|
void _fix() {
|
||||||
|
while (curr < pool->_size and not pool->_table[curr]) {
|
||||||
|
++curr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
table_t _table;
|
table_t _table;
|
||||||
freed_t _freed;
|
freed_t _freed;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
|
|
||||||
static void log(const cstring& str,
|
static void log(const cstring& str,
|
||||||
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
||||||
const char* const _file = FENNEC_BUILTIN_FILE()
|
const char* _file = FENNEC_BUILTIN_FILE()
|
||||||
) {
|
) {
|
||||||
logger& inst = instance();
|
logger& inst = instance();
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ public:
|
|||||||
|
|
||||||
static void log(const string& str,
|
static void log(const string& str,
|
||||||
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
||||||
const char* const _file = FENNEC_BUILTIN_FILE()
|
const char* _file = FENNEC_BUILTIN_FILE()
|
||||||
) {
|
) {
|
||||||
logger& inst = instance();
|
logger& inst = instance();
|
||||||
|
|
||||||
|
|||||||
45
include/fennec/lang/detail/_function.h
Normal file
45
include/fennec/lang/detail/_function.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file _function.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_LANG_DETAIL_FUNCTION_H
|
||||||
|
#define FENNEC_LANG_DETAIL_FUNCTION_H
|
||||||
|
|
||||||
|
#include <fennec/lang/utility.h>
|
||||||
|
|
||||||
|
namespace fennec::detail
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_LANG_DETAIL_FUNCTION_H
|
||||||
@@ -55,6 +55,12 @@ namespace fennec::detail
|
|||||||
template<> struct _is_integral<llong_t> : true_type {};
|
template<> struct _is_integral<llong_t> : true_type {};
|
||||||
template<> struct _is_integral<ullong_t> : true_type {};
|
template<> struct _is_integral<ullong_t> : true_type {};
|
||||||
|
|
||||||
|
template<typename> struct _is_const : false_type {};
|
||||||
|
template<typename T> struct _is_const<const T> : true_type {};
|
||||||
|
|
||||||
|
template<typename> struct _is_volatile : false_type {};
|
||||||
|
template<typename T> struct _is_volatile<volatile T> : true_type {};
|
||||||
|
|
||||||
// Most unsigned types will underflow `-1` to the types maximum value
|
// Most unsigned types will underflow `-1` to the types maximum value
|
||||||
template<typename TypeT> struct _is_signed : bool_constant<TypeT(-1) < TypeT(0)> {};
|
template<typename TypeT> struct _is_signed : bool_constant<TypeT(-1) < TypeT(0)> {};
|
||||||
template<typename TypeT> struct _is_unsigned : bool_constant<TypeT(-1) >= TypeT(0)> {};
|
template<typename TypeT> struct _is_unsigned : bool_constant<TypeT(-1) >= TypeT(0)> {};
|
||||||
|
|||||||
@@ -20,9 +20,39 @@
|
|||||||
#define FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H
|
#define FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H
|
||||||
|
|
||||||
#include <fennec/lang/types.h>
|
#include <fennec/lang/types.h>
|
||||||
|
#include <fennec/lang/detail/_type_traits.h>
|
||||||
|
|
||||||
namespace fennec::detail
|
namespace fennec::detail
|
||||||
{
|
{
|
||||||
|
template<typename TypeT> struct _add_pointer : type_identity<TypeT*> {};
|
||||||
|
template<typename TypeT> struct _remove_pointer : type_identity<TypeT> {};
|
||||||
|
template<typename TypeT> struct _remove_pointer<TypeT*> : type_identity<TypeT> {};
|
||||||
|
|
||||||
|
template<typename TypeT> struct _add_const : type_identity<const TypeT> {};
|
||||||
|
template<typename TypeT> struct _remove_const : type_identity<TypeT> {};
|
||||||
|
template<typename TypeT> struct _remove_const<const TypeT> : type_identity<TypeT> {};
|
||||||
|
|
||||||
|
template<typename TypeT> struct _add_volatile : type_identity<volatile TypeT> {};
|
||||||
|
template<typename TypeT> struct _remove_volatile : type_identity<TypeT> {};
|
||||||
|
template<typename TypeT> struct _remove_volatile<volatile TypeT> : type_identity<TypeT> {};
|
||||||
|
|
||||||
|
template<typename TypeT> struct _add_cv : _add_const<typename _add_volatile<TypeT>::type> {};
|
||||||
|
template<typename TypeT> struct _remove_cv : type_identity<TypeT> {};
|
||||||
|
template<typename TypeT> struct _remove_cv<const TypeT> : type_identity<TypeT> {};
|
||||||
|
template<typename TypeT> struct _remove_cv<volatile TypeT> : type_identity<TypeT> {};
|
||||||
|
template<typename TypeT> struct _remove_cv<const volatile TypeT> : type_identity<TypeT> {};
|
||||||
|
|
||||||
|
template<typename TypeT>
|
||||||
|
struct _decay : conditional<_is_const<const TypeT>{}, _remove_cv<TypeT>, _add_pointer<TypeT>> {};
|
||||||
|
|
||||||
|
template<typename TypeT> requires requires { typename TypeT::element_t; }
|
||||||
|
struct _decay<TypeT> : type_identity<typename TypeT::decay_t> {};
|
||||||
|
|
||||||
|
template<typename TypeT, size_t N>
|
||||||
|
struct _decay<TypeT[N]> : type_identity<TypeT*> {};
|
||||||
|
|
||||||
|
template<typename TypeT>
|
||||||
|
struct _decay<TypeT[]> : type_identity<TypeT*> {};
|
||||||
|
|
||||||
template<typename _Tp, typename = void>
|
template<typename _Tp, typename = void>
|
||||||
struct _add_lvalue_reference {
|
struct _add_lvalue_reference {
|
||||||
|
|||||||
87
include/fennec/lang/function.h
Normal file
87
include/fennec/lang/function.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file function.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_LANG_FUNCTION_H
|
||||||
|
#define FENNEC_LANG_FUNCTION_H
|
||||||
|
|
||||||
|
#include <fennec/lang/types.h>
|
||||||
|
#include <fennec/lang/assert.h>
|
||||||
|
#include <fennec/lang/utility.h>
|
||||||
|
|
||||||
|
#include <fennec/lang/detail/_function.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename> class function;
|
||||||
|
|
||||||
|
template<typename ReturnT, typename...ArgsT>
|
||||||
|
class function<ReturnT(ArgsT...)> {
|
||||||
|
public:
|
||||||
|
constexpr function() noexcept = default;
|
||||||
|
constexpr ~function() = default;
|
||||||
|
|
||||||
|
constexpr function(const function&) noexcept = default;
|
||||||
|
constexpr function( function&&) noexcept = default;
|
||||||
|
|
||||||
|
constexpr function(ReturnT (*func)(ArgsT...))
|
||||||
|
: call(func) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr function(nullptr_t) noexcept : function() {}
|
||||||
|
|
||||||
|
constexpr function& operator=(const function&) = default;
|
||||||
|
constexpr function& operator=(function&&) = default;
|
||||||
|
|
||||||
|
constexpr function& operator=(nullptr_t) {
|
||||||
|
call = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr function& operator=(ReturnT (*func)(ArgsT...)) {
|
||||||
|
call = func;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr operator bool() const noexcept { return call != nullptr; }
|
||||||
|
|
||||||
|
ReturnT operator()(ArgsT...args) const noexcept {
|
||||||
|
assertf(call != nullptr, "Attempted to call a null function object!");
|
||||||
|
return call(fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReturnT (*call)(ArgsT&&...) { nullptr };
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_LANG_FUNCTION_H
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <fennec/lang/types.h>
|
#include <fennec/lang/types.h>
|
||||||
#include <fennec/lang/type_traits.h>
|
#include <fennec/lang/type_traits.h>
|
||||||
|
#include <fennec/lang/bits.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -176,6 +176,27 @@
|
|||||||
# define FENNEC_HAS_BUILTIN_IS_CLASS
|
# define FENNEC_HAS_BUILTIN_IS_CLASS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __has_builtin(__is_member_pointer)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_MEMBER_POINTER 1
|
||||||
|
# define FENNEC_BUILTIN_IS_MEMBER_POINTER(arg) __is_member_pointer(arg)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_MEMBER_POINTER 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_builtin(__is_member_function_pointer)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_MEMBER_FUNCTION_POINTER 1
|
||||||
|
# define FENNEC_BUILTIN_IS_MEMBER_FUNCTION_POINTER(arg) __is_member_function_pointer(arg)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_MEMBER_FUNCTION_POINTER 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_builtin(__is_member_object_pointer)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_MEMBER_OBJECT_POINTER 1
|
||||||
|
# define FENNEC_BUILTIN_IS_MEMBER_OBJECT_POINTER(arg) __is_member_object_pointer(arg)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_MEMBER_OBJECT_POINTER 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// CONSTRUCTORS ========================================================================================================
|
// CONSTRUCTORS ========================================================================================================
|
||||||
|
|
||||||
@@ -214,6 +235,38 @@
|
|||||||
# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 0
|
# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Inconsistent without intrinsics
|
||||||
|
#if __has_builtin(__is_trivial)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_TRIVIAL 1
|
||||||
|
# define FENNEC_BUILTIN_IS_TRIVIAL(a) __is_trivial(a)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_TRIVIAL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Difficult and Inconsistent without intrinsics
|
||||||
|
#if __has_builtin(__is_trivially_copyable)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_COPYABLE 1
|
||||||
|
# define FENNEC_BUILTIN_IS_TRIVIALLY_COPYABLE(a) __is_trivially_copyable(a)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_COPYABLE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Impossible without instrinsics
|
||||||
|
#if __has_builtin(__is_standard_layout)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 1
|
||||||
|
# define FENNEC_BUILTIN_IS_STANDARD_LAYOUT(arg) __is_standard_layout(arg)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Impossible without instrinsics
|
||||||
|
#if __has_builtin(__has_unique_object_representations)
|
||||||
|
# define FENNEC_HAS_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS 1
|
||||||
|
# define FENNEC_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS(arg) __has_unique_object_representations(arg)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Type Traits
|
// Type Traits
|
||||||
// can_convert is also very difficult to implement without intrinsics
|
// can_convert is also very difficult to implement without intrinsics
|
||||||
@@ -264,6 +317,22 @@
|
|||||||
# define FENNEC_HAS_BUILTIN_IS_FINAL 0
|
# define FENNEC_HAS_BUILTIN_IS_FINAL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Inconsistent without intrinsics
|
||||||
|
#if __has_builtin(__is_aggregate)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_AGGREGATE 1
|
||||||
|
# define FENNEC_BUILTIN_IS_AGGREGATE(arg) __is_aggregate(arg)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_AGGREGATE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Inconsistent without intrinsics
|
||||||
|
#if __has_builtin(__builtin_is_implicit_lifetime)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_IMPLICIT_LIFETIME 1
|
||||||
|
# define FENNEC_BUILTIN_IS_IMPLICIT_LIFETIME(arg) __builtin_is_implicit_lifetime(arg)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_IMPLICIT_LIFETIME 0
|
||||||
|
#endif
|
||||||
|
|
||||||
// Inconsistent without intrinsics
|
// Inconsistent without intrinsics
|
||||||
#if __has_builtin(__is_function)
|
#if __has_builtin(__is_function)
|
||||||
# define FENNEC_HAS_BUILTIN_IS_FUNCTION 1
|
# define FENNEC_HAS_BUILTIN_IS_FUNCTION 1
|
||||||
@@ -288,14 +357,6 @@
|
|||||||
# define FENNEC_HAS_BUILTIN_IS_POLYMORPHIC 0
|
# define FENNEC_HAS_BUILTIN_IS_POLYMORPHIC 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Impossible without instrinsics
|
|
||||||
#if __has_builtin(__is_standard_layout)
|
|
||||||
# define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 1
|
|
||||||
# define FENNEC_BUILTIN_IS_STANDARD_LAYOUT(arg) __is_standard_layout(arg)
|
|
||||||
#else
|
|
||||||
# define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// For compilers without or differently named builtins
|
// For compilers without or differently named builtins
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -147,18 +147,18 @@
|
|||||||
/// <th style="vertical-align: top">Description
|
/// <th style="vertical-align: top">Description
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::is_fundamental "is_fundamental<TypeT>::value"<br>
|
|
||||||
/// \ref fennec::is_fundamental_v "is_fundamental_v<TypeT>"
|
|
||||||
/// <td width="50%" style="vertical-align: top">
|
|
||||||
/// \copydetails fennec::is_fundamental
|
|
||||||
///
|
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
|
||||||
/// \ref fennec::is_arithmetic "is_arithmetic<TypeT>::value"<br>
|
/// \ref fennec::is_arithmetic "is_arithmetic<TypeT>::value"<br>
|
||||||
/// \ref fennec::is_arithmetic_v "is_arithmetic_v<TypeT>"
|
/// \ref fennec::is_arithmetic_v "is_arithmetic_v<TypeT>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydetails fennec::is_arithmetic
|
/// \copydetails fennec::is_arithmetic
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_fundamental "is_fundamental<TypeT>::value"<br>
|
||||||
|
/// \ref fennec::is_fundamental_v "is_fundamental_v<TypeT>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydetails fennec::is_fundamental
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::is_scalar "is_scalar<TypeT>::value"<br>
|
/// \ref fennec::is_scalar "is_scalar<TypeT>::value"<br>
|
||||||
/// \ref fennec::is_scalar_v "is_scalar_v<TypeT>"
|
/// \ref fennec::is_scalar_v "is_scalar_v<TypeT>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
@@ -271,12 +271,6 @@
|
|||||||
/// \copydetails fennec::is_aggregate
|
/// \copydetails fennec::is_aggregate
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::is_implicit_lifetime "is_implicit_lifetime<TypeT>::value"<br>
|
|
||||||
/// \ref fennec::is_implicit_lifetime_v "is_implicit_lifetime_v<TypeT>"
|
|
||||||
/// <td width="50%" style="vertical-align: top">
|
|
||||||
/// \copydetails fennec::is_implicit_lifetime
|
|
||||||
///
|
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
|
||||||
/// \ref fennec::is_signed "is_signed<TypeT>::value"<br>
|
/// \ref fennec::is_signed "is_signed<TypeT>::value"<br>
|
||||||
/// \ref fennec::is_signed_v "is_signed_v<TypeT>"
|
/// \ref fennec::is_signed_v "is_signed_v<TypeT>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
@@ -451,7 +445,7 @@ constexpr inline bool is_constant_evaluated() noexcept {
|
|||||||
/// \details Stores a boolean value in `is_void::value`, representing whether the provided type is of base type void.
|
/// \details Stores a boolean value in `is_void::value`, representing whether the provided type is of base type void.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_void
|
template<typename T> struct is_void
|
||||||
: detail::_is_void<remove_cvr_t<T>>{};
|
: detail::_is_void<remove_cvref_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Shorthand for ```is_void<T>::value```
|
/// \brief Shorthand for ```is_void<T>::value```
|
||||||
@@ -468,7 +462,7 @@ template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
|
|||||||
/// \details Stores a boolean value in `is_null_pointer::value`, representing whether the provided type is of base type nullptr_t.
|
/// \details Stores a boolean value in `is_null_pointer::value`, representing whether the provided type is of base type nullptr_t.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_null_pointer
|
template<typename T> struct is_null_pointer
|
||||||
: detail::_is_null_pointer<remove_cvr_t<T>>{};
|
: detail::_is_null_pointer<remove_cvref_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Shorthand for ```is_null_pointer<T>::value```
|
/// \brief Shorthand for ```is_null_pointer<T>::value```
|
||||||
@@ -477,6 +471,57 @@ template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::va
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_bool =====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is of type bool
|
||||||
|
///
|
||||||
|
/// \details Stores a boolean value in `is_bool::value`, representing whether the provided type is of base type bool.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_bool
|
||||||
|
: detail::_is_bool<remove_cvref_t<T>>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_bool<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_bool_v = is_bool<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_integral =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is of an integral
|
||||||
|
///
|
||||||
|
/// \details Stores a boolean value in `is_integral::value`, representing whether the provided type is of a base integer type.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_integral
|
||||||
|
: detail::_is_integral<remove_cvref_t<T>> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_integral<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_floating_point ===========================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is of a floating point type
|
||||||
|
///
|
||||||
|
/// \details Stores a boolean value in `is_floating_point::value`, representing whether the provided type is of a base floating point type.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_floating_point
|
||||||
|
: detail::_is_floating_point<remove_cvref_t<T>>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_array ====================================================================================================
|
// fennec::is_array ====================================================================================================
|
||||||
|
|
||||||
#ifdef FENNEC_BUILTIN_IS_ARRAY
|
#ifdef FENNEC_BUILTIN_IS_ARRAY
|
||||||
@@ -557,7 +602,7 @@ template<typename T> constexpr size_t is_class_v = is_class<T>::value;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_function ====================================================================================================
|
// fennec::is_function =================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if \p T is a class
|
/// \brief Check if \p T is a class
|
||||||
@@ -572,41 +617,363 @@ template<typename T> constexpr size_t is_function_v = is_function<T>::value;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Integral Types ======================================================================================================
|
// fennec::is_pointer ==================================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_bool =====================================================================================================
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if \p T is of type bool
|
/// \brief Check if \p T is of a pointer type
|
||||||
///
|
///
|
||||||
/// \details Stores a boolean value in `is_bool::value`, representing whether the provided type is of base type bool.
|
/// \details Stores a boolean value in `is_pointer::value`, representing whether the provided type is of a base pointer type.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_bool
|
template<typename T> struct is_pointer
|
||||||
: detail::_is_bool<remove_cvr_t<T>>{};
|
: detail::_is_pointer<remove_cvref_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Shorthand for ```is_bool<T>::value```
|
/// \brief Shorthand for ```is_pointer<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_bool_v = is_bool<T>::value;
|
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_integral =================================================================================================
|
// fennec::is_lvalue_reference =========================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if \p T is of an integral
|
/// \brief Check if \p T is of a floating point type
|
||||||
///
|
///
|
||||||
/// \details Stores a boolean value in `is_integral::value`, representing whether the provided type is of a base integer type.
|
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_integral
|
template<typename T> struct is_lvalue_reference
|
||||||
: detail::_is_integral<remove_cvr_t<T>> {};
|
: detail::_is_lvalue_reference<T>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Shorthand for ```is_integral<T>::value```
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
|
template<typename T> constexpr bool_t is_lvalue_reference_v = is_lvalue_reference<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_rvalue_reference =========================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is of a floating point type
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_rvalue_reference
|
||||||
|
: detail::_is_rvalue_reference<T>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_rvalue_reference_v = is_rvalue_reference<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_member_function_pointer ==================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a pointer to a member function
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is pointer to a member function and store it in `is_member_function_pointer::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_member_function_pointer
|
||||||
|
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_FUNCTION_POINTER(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_member_function_pointer<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_member_function_pointer_v = is_member_function_pointer<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_member_object_pointer ====================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a pointer to a member object
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is pointer to a member object and store it in `is_member_object_pointer::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_member_object_pointer
|
||||||
|
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_OBJECT_POINTER(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_member_object_pointer<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_member_object_pointer_v = is_member_object_pointer<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_arithmetic ===============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is an arithmetic type
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_arithmetic
|
||||||
|
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_arithmetic<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_fundamental ==============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a fundamental type, i.e. arithmetic, void, or nullptr_t
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_fundamental
|
||||||
|
: bool_constant<is_arithmetic_v<T> or is_void_v<T> or is_null_pointer_v<T>>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_fundamental<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_scalar ===================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is an arithmetic type
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_scalar
|
||||||
|
: bool_constant<is_arithmetic_v<T> or is_enum_v<T> or is_pointer_v<T>>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_scalar<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_scalar_v = is_scalar<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_object ===================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is an object
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is an object and store it in `is_same::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_object : bool_constant<FENNEC_BUILTIN_IS_OBJECT(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_object<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_object_v = is_object<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_compound =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a object compound type
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is an object and store it in `is_same::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_compound : bool_constant<not is_fundamental_v<T>> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_compound<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_compound_v = is_compound<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_reference ================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is of a floating point type
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_reference
|
||||||
|
: detail::_is_reference<T>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_reference_v = is_reference<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_member_pointer ===========================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a pointer to a member
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is pointer to a member and store it in `is_member_function_pointer::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_member_pointer
|
||||||
|
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_POINTER(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_member_function_pointer<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_member_pointer_v = is_member_pointer<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_trivial ==================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is trivial
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_trivial : bool_constant<FENNEC_BUILTIN_IS_TRIVIAL(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_trivial<T>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_trivial_v = is_trivial<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_trivially_copyable =======================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is trivially_copyable
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_trivially_copyable : bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_COPYABLE(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_trivially_copyable<T>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_trivially_copyable_v = is_trivially_copyable<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_standard_layout ==========================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is standard_layout
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_standard_layout : bool_constant<FENNEC_BUILTIN_IS_STANDARD_LAYOUT(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_standard_layout<T>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_standard_layout_v = is_standard_layout<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::has_unique_object_representations ===========================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` has unique object representations
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct has_unique_object_representations
|
||||||
|
: bool_constant<FENNEC_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS(remove_cv_t<T>)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `has_unique_object_representations<T>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t has_unique_object_representations_v = has_unique_object_representations<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_empty ====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is empty
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_empty : bool_constant<FENNEC_BUILTIN_IS_EMPTY(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_empty<T>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_empty_v = is_empty<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_polymorphic ==============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is polymorphic
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_polymorphic : bool_constant<FENNEC_BUILTIN_IS_POLYMORPHIC(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_polymorphic<T>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_polymorphic_v = is_polymorphic<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_abstract =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is abstract
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_abstract : bool_constant<FENNEC_BUILTIN_IS_ABSTRACT(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_abstract<T>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_abstract_v = is_abstract<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_complete =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is complete
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_complete : detail::_is_complete<T>::type {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_complete<T>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_complete_v = is_complete<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_final =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is final
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_final : bool_constant<FENNEC_BUILTIN_IS_FINAL(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_final<T>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_final_v = is_final<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_aggregate =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is aggregate
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_aggregate : bool_constant<FENNEC_BUILTIN_IS_AGGREGATE(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_aggregate<T>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_aggregate_v = is_aggregate<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -619,7 +986,7 @@ template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
|
|||||||
/// \details Checks if type `T` is a signed type i.e. `T(-1) < T(0)` and stores it in `is_same::value`.
|
/// \details Checks if type `T` is a signed type i.e. `T(-1) < T(0)` and stores it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_signed
|
template<typename T> struct is_signed
|
||||||
: detail::_is_signed<remove_cvr_t<T>> {};
|
: detail::_is_signed<remove_cvref_t<T>> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Shorthand for ```is_signed<T>::value```
|
/// \brief Shorthand for ```is_signed<T>::value```
|
||||||
@@ -637,138 +1004,12 @@ template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
|
|||||||
/// \details Checks if type `T` is an unsigned type i.e. `T(-1) > T(0)` and stores it in `is_same::value`.
|
/// \details Checks if type `T` is an unsigned type i.e. `T(-1) > T(0)` and stores it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_unsigned
|
template<typename T> struct is_unsigned
|
||||||
: detail::_is_unsigned<remove_cvr_t<T>> {};
|
: detail::_is_unsigned<remove_cvref_t<T>> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Shorthand for ```is_unsigned<T>::value```
|
/// \brief Shorthand for ```is_unsigned<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
|
template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Floating Point Types ================================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if \p T is of a floating point type
|
|
||||||
///
|
|
||||||
/// \details Stores a boolean value in `is_floating_point::value`, representing whether the provided type is of a base floating point type.
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_floating_point
|
|
||||||
: detail::_is_floating_point<remove_cvr_t<T>>{};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for ```is_floating_point<T>::value```
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {};
|
|
||||||
|
|
||||||
|
|
||||||
// Pointer Types =======================================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if \p T is of a pointer type
|
|
||||||
///
|
|
||||||
/// \details Stores a boolean value in `is_pointer::value`, representing whether the provided type is of a base pointer type.
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_pointer
|
|
||||||
: detail::_is_pointer<remove_cvr_t<T>>{};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for ```is_pointer<T>::value```
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
|
|
||||||
|
|
||||||
|
|
||||||
// Reference Types =======================================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if \p T is of a floating point type
|
|
||||||
///
|
|
||||||
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_reference
|
|
||||||
: detail::_is_reference<T>{};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for ```is_floating_point<T>::value```
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_reference_v = is_reference<T> {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if \p T is of a floating point type
|
|
||||||
///
|
|
||||||
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_lvalue_reference
|
|
||||||
: detail::_is_lvalue_reference<T>{};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for ```is_floating_point<T>::value```
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_lvalue_reference_v = is_lvalue_reference<T> {};
|
|
||||||
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if \p T is of a floating point type
|
|
||||||
///
|
|
||||||
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_rvalue_reference
|
|
||||||
: detail::_is_rvalue_reference<T>{};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for ```is_floating_point<T>::value```
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_rvalue_reference_v = is_rvalue_reference<T> {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Arithmetic Types ====================================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if \p T is an arithmetic type
|
|
||||||
///
|
|
||||||
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_arithmetic
|
|
||||||
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for ```is_arithmetic<T>::value```
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Arithmetic Types ====================================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if \p T is an arithmetic type
|
|
||||||
///
|
|
||||||
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_scalar
|
|
||||||
: bool_constant<is_arithmetic_v<T> or is_enum_v<T> or is_pointer_v<T>>{};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for ```is_scalar<T>::value```
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_scalar_v = is_scalar<T>::value;
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_fundamental ==============================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if \p T is a fundamental type, i.e. arithmetic, void, or nullptr_t
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_fundamental
|
|
||||||
: bool_constant<is_arithmetic_v<T> || is_void_v<T> || is_null_pointer_v<T>>{};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for ```is_fundamental<T>::value```
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::value;
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_same =====================================================================================================
|
// fennec::is_same =====================================================================================================
|
||||||
@@ -791,7 +1032,7 @@ template<typename T> struct is_same<T, T> : true_type {};
|
|||||||
template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
|
template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_base_of =====================================================================================================
|
// fennec::is_base_of ==================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `Derived` has a base type of `Base`
|
/// \brief Check if `Derived` has a base type of `Base`
|
||||||
@@ -809,61 +1050,7 @@ template<typename Base, typename Derived> struct is_base_of : bool_constant<
|
|||||||
/// \tparam Derived derived type to check
|
/// \tparam Derived derived type to check
|
||||||
template<typename Base, typename Derived> constexpr bool_t is_base_of_v = is_base_of<Base, Derived> {};
|
template<typename Base, typename Derived> constexpr bool_t is_base_of_v = is_base_of<Base, Derived> {};
|
||||||
|
|
||||||
// fennec::is_complete ==============================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if type `T` is complete
|
|
||||||
///
|
|
||||||
/// \details Checks if `T`
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_complete : detail::_is_complete<T>::type {};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for `is_complete<TypeT0, TypeT1>::value`
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_complete_v = is_complete<T>{};
|
|
||||||
|
|
||||||
// fennec::is_iterable ==============================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if type `T` is iterable
|
|
||||||
///
|
|
||||||
/// \details Checks if `T`
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_iterable : decltype(detail::_is_iterable<T>(0)) {};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for `is_iterable<TypeT0, TypeT1>::value`
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_iterable_v = is_iterable<T>{};
|
|
||||||
|
|
||||||
// fennec::is_indexable ==============================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if type `T` is indexable
|
|
||||||
///
|
|
||||||
/// \details Checks if `T`
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_indexable : decltype(detail::_is_indexable<T>(0)) {};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for `is_indexable<TypeT0, TypeT1>::value`
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_indexable_v = is_indexable<T>{};
|
|
||||||
|
|
||||||
// fennec::is_mappable ==============================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if type `T` is mappable
|
|
||||||
///
|
|
||||||
/// \details Checks if `T`
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> struct is_mappable : decltype(detail::_is_mappable<T>(0)) {};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for `is_mappable<TypeT0, TypeT1>::value`
|
|
||||||
/// \tparam T type to check
|
|
||||||
template<typename T> constexpr bool_t is_mappable_v = is_mappable<T>{};
|
|
||||||
|
|
||||||
// fennec::is_convertible ==============================================================================================
|
// fennec::is_convertible ==============================================================================================
|
||||||
|
|
||||||
@@ -883,6 +1070,7 @@ template<typename FromT, typename ToT> struct is_convertible
|
|||||||
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{};
|
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_constructible ============================================================================================
|
// fennec::is_constructible ============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -899,6 +1087,8 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_trivially_constructible ==================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is trivially constructible
|
/// \brief Check if `ClassT` is trivially constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
@@ -911,6 +1101,8 @@ template<typename ClassT> constexpr bool_t is_trivially_constructible_v = is_tri
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_default_constructible ====================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is default constructible
|
/// \brief Check if `ClassT` is default constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
@@ -923,6 +1115,8 @@ template<typename ClassT> constexpr bool_t is_default_constructible_v = is_defau
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_copy_constructible =======================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is copy constructible
|
/// \brief Check if `ClassT` is copy constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
@@ -935,8 +1129,10 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_copy_constructib
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_move_constructible =======================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Check if `ClassT` is copy constructible
|
/// \brief Check if `ClassT` is move constructible
|
||||||
/// \tparam ClassT The class type to test
|
/// \tparam ClassT The class type to test
|
||||||
template<typename ClassT> struct is_move_constructible
|
template<typename ClassT> struct is_move_constructible
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_rvalue_reference_t<ClassT>)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_rvalue_reference_t<ClassT>)> {};
|
||||||
@@ -946,42 +1142,6 @@ template<typename ClassT> struct is_move_constructible
|
|||||||
template<typename ClassT, typename...ArgsT> constexpr bool_t is_move_constructible_v = is_move_constructible<ClassT>{};
|
template<typename ClassT, typename...ArgsT> constexpr bool_t is_move_constructible_v = is_move_constructible<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_destructible ===================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if `ClassT` is destructible
|
|
||||||
/// \tparam ClassT The class type to test
|
|
||||||
template<typename ClassT> struct is_destructible
|
|
||||||
: detail::_is_destructible<ClassT>::type {};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for `is_destructible<ClassT, ArgsT...>::value`
|
|
||||||
template<typename ClassT> constexpr bool_t is_destructible_v = is_destructible<ClassT>{};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if `ClassT` is trivially destructible
|
|
||||||
/// \tparam ClassT The class type to test
|
|
||||||
template<typename ClassT> struct is_trivially_destructible
|
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(ClassT)> {};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for `is_trivially_destructible<ClassT, ArgsT...>::value`
|
|
||||||
template<typename ClassT> constexpr bool_t is_trivially_destructible_v = is_trivially_destructible<ClassT>{};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if `ClassT` is nothrow destructible
|
|
||||||
/// \tparam ClassT The class type to test
|
|
||||||
template<typename ClassT> struct is_nothrow_destructible
|
|
||||||
: detail::_is_nothrow_destructible<ClassT>::type {};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Shorthand for `is_nothrow_destructible<ClassT, ArgsT...>::value`
|
|
||||||
template<typename ClassT> constexpr bool_t is_nothrow_destructible_v = is_nothrow_destructible<ClassT>{};
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_assignable ===============================================================================================
|
// fennec::is_assignable ===============================================================================================
|
||||||
|
|
||||||
@@ -998,6 +1158,7 @@ template<typename ClassAT, typename ClassBT> struct is_assignable
|
|||||||
template<typename ClassT, typename...ArgsT> constexpr bool_t is_assignable_v = is_assignable<ClassT, ArgsT...>{};
|
template<typename ClassT, typename...ArgsT> constexpr bool_t is_assignable_v = is_assignable<ClassT, ArgsT...>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_copy_assignable ==========================================================================================
|
// fennec::is_copy_assignable ==========================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -1011,6 +1172,7 @@ template<typename ClassT> struct is_copy_assignable
|
|||||||
template<typename ClassT> constexpr bool_t is_copy_assignable_v = is_copy_assignable<ClassT>{};
|
template<typename ClassT> constexpr bool_t is_copy_assignable_v = is_copy_assignable<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_move_assignable ==========================================================================================
|
// fennec::is_move_assignable ==========================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -1024,6 +1186,96 @@ template<typename ClassT> struct is_move_assignable
|
|||||||
template<typename ClassT> constexpr bool_t is_move_assignable_v = is_move_assignable<ClassT>{};
|
template<typename ClassT> constexpr bool_t is_move_assignable_v = is_move_assignable<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_destructible =============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if `ClassT` is destructible
|
||||||
|
/// \tparam ClassT The class type to test
|
||||||
|
template<typename ClassT> struct is_destructible
|
||||||
|
: detail::_is_destructible<ClassT>::type {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_destructible<ClassT, ArgsT...>::value`
|
||||||
|
template<typename ClassT> constexpr bool_t is_destructible_v = is_destructible<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_trivially_destructible ===================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if `ClassT` is trivially destructible
|
||||||
|
/// \tparam ClassT The class type to test
|
||||||
|
template<typename ClassT> struct is_trivially_destructible
|
||||||
|
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(ClassT)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_trivially_destructible<ClassT, ArgsT...>::value`
|
||||||
|
template<typename ClassT> constexpr bool_t is_trivially_destructible_v = is_trivially_destructible<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_nothrow_destructible =====================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if `ClassT` is nothrow destructible
|
||||||
|
/// \tparam ClassT The class type to test
|
||||||
|
template<typename ClassT> struct is_nothrow_destructible
|
||||||
|
: detail::_is_nothrow_destructible<ClassT>::type {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_nothrow_destructible<ClassT, ArgsT...>::value`
|
||||||
|
template<typename ClassT> constexpr bool_t is_nothrow_destructible_v = is_nothrow_destructible<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_iterable =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is iterable
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_iterable : decltype(detail::_is_iterable<T>(0)) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_iterable<TypeT0, TypeT1>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_iterable_v = is_iterable<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_indexable ================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is indexable
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_indexable : decltype(detail::_is_indexable<T>(0)) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_indexable<TypeT0, TypeT1>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_indexable_v = is_indexable<T>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_mappable =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if type `T` is mappable
|
||||||
|
///
|
||||||
|
/// \details Checks if `T`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_mappable : decltype(detail::_is_mappable<T>(0)) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_mappable<TypeT0, TypeT1>::value`
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_mappable_v = is_mappable<T>{};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_LANG_TYPE_TRAITS_H
|
#endif // FENNEC_LANG_TYPE_TRAITS_H
|
||||||
|
|||||||
@@ -127,6 +127,12 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Decay Conversions ===================================================================================================
|
||||||
|
|
||||||
|
template<typename T> struct decay : detail::_decay<T> {};
|
||||||
|
|
||||||
|
template<typename T> using decay_t = typename decay<T>::type;
|
||||||
|
|
||||||
// Pointer Conversions =================================================================================================
|
// Pointer Conversions =================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -134,7 +140,7 @@ namespace fennec
|
|||||||
///
|
///
|
||||||
/// \details adds a pointer to the provided type such that `T` becomes `T*`
|
/// \details adds a pointer to the provided type such that `T` becomes `T*`
|
||||||
/// \tparam T Resultant Type
|
/// \tparam T Resultant Type
|
||||||
template<typename T> struct add_pointer : type_identity<T*>{};
|
template<typename T> struct add_pointer : detail::_add_pointer<T>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `typename add_pointer<T>::type`
|
/// \brief shorthand for `typename add_pointer<T>::type`
|
||||||
@@ -146,10 +152,7 @@ template<typename T> using add_pointer_t = typename add_pointer<T>::type;
|
|||||||
///
|
///
|
||||||
/// \details removes a pointer from the provided type such that `T*` becomes `T`
|
/// \details removes a pointer from the provided type such that `T*` becomes `T`
|
||||||
/// \tparam T Resultant Type
|
/// \tparam T Resultant Type
|
||||||
template<typename T> struct remove_pointer : type_identity<T> {};
|
template<typename T> struct remove_pointer : detail::_remove_pointer<T> {};
|
||||||
|
|
||||||
// specialization for T*
|
|
||||||
template<typename T> struct remove_pointer<T*> : type_identity<T> {};
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `typename remove_pointer<T>::type`
|
/// \brief shorthand for `typename remove_pointer<T>::type`
|
||||||
@@ -235,30 +238,24 @@ template<typename T> using add_rvalue_reference_t = typename add_rvalue_referen
|
|||||||
///
|
///
|
||||||
/// \details adds const qualification to the provided type such that `T` becomes `const T`
|
/// \details adds const qualification to the provided type such that `T` becomes `const T`
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct add_const : type_identity<const T> {};
|
template<typename T> struct add_const : detail::_add_const<T> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `typename add_const<T>::type`
|
/// \brief shorthand for `typename add_const<T>::type`
|
||||||
template<typename T> using add_const_t = typename add_const<T>::type;
|
template<typename T> using add_const_t = typename add_const<T>::type;
|
||||||
|
|
||||||
// specialization for const types
|
|
||||||
template<typename T> struct add_const<const T> : type_identity<const T> {};
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief remove the const qualifier from the provided type \p T
|
/// \brief remove the const qualifier from the provided type \p T
|
||||||
///
|
///
|
||||||
/// \details removes const qualification from the provided type such that `const T` becomes `T`
|
/// \details removes const qualification from the provided type such that `const T` becomes `T`
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct remove_const : type_identity<T> {};
|
template<typename T> struct remove_const : detail::_remove_const<T> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `typename remove_const<T>::type`
|
/// \brief shorthand for `typename remove_const<T>::type`
|
||||||
template<typename T> using remove_const_t = typename remove_const<T>::type;
|
template<typename T> using remove_const_t = typename remove_const<T>::type;
|
||||||
|
|
||||||
// specialization for const types
|
|
||||||
template<typename T> struct remove_const<const T> : type_identity<T> {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -266,30 +263,24 @@ template<typename T> struct remove_const<const T> : type_identity<T> {};
|
|||||||
///
|
///
|
||||||
/// \details removes references from the provided type such that `T` becomes `volatile T`
|
/// \details removes references from the provided type such that `T` becomes `volatile T`
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct add_volatile : type_identity<volatile T> {};
|
template<typename T> struct add_volatile : detail::_add_volatile<T> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `typename add_volatile<T>::type`
|
/// \brief shorthand for `typename add_volatile<T>::type`
|
||||||
template<typename T> using add_volatile_t = typename add_volatile<T>::type;
|
template<typename T> using add_volatile_t = typename add_volatile<T>::type;
|
||||||
|
|
||||||
// specialization for volatile types
|
|
||||||
template<typename T> struct add_volatile<volatile T> : type_identity<volatile T> {};
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief remove the volatile qualifier from the provided type \p T
|
/// \brief remove the volatile qualifier from the provided type \p T
|
||||||
///
|
///
|
||||||
/// \details removes references from the provided type such that `volatile T` becomes `T`
|
/// \details removes references from the provided type such that `volatile T` becomes `T`
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct remove_volatile : type_identity<T> {};
|
template<typename T> struct remove_volatile : detail::_remove_volatile<T> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `typename remove_volatile<T>::type`
|
/// \brief shorthand for `typename remove_volatile<T>::type`
|
||||||
template<typename T> using remove_volatile_t = typename remove_volatile<T>::type;
|
template<typename T> using remove_volatile_t = typename remove_volatile<T>::type;
|
||||||
|
|
||||||
// specialization for volatile types
|
|
||||||
template<typename T> struct remove_volatile<volatile T> : type_identity<T> {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -298,21 +289,12 @@ template<typename T> struct remove_volatile<volatile T> : type_identity<T> {};
|
|||||||
/// \details removes references from the provided type such that `T`, `const T`, and `volatile T` become
|
/// \details removes references from the provided type such that `T`, `const T`, and `volatile T` become
|
||||||
/// `const volatile T`
|
/// `const volatile T`
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct add_cv : type_identity<const volatile T> {};
|
template<typename T> struct add_cv : detail::_add_cv<T> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `typename add_cv<T>::type`
|
/// \brief shorthand for `typename add_cv<T>::type`
|
||||||
template<typename T> using add_cv_t = typename add_cv<T>::type;
|
template<typename T> using add_cv_t = typename add_cv<T>::type;
|
||||||
|
|
||||||
// specialization for const types
|
|
||||||
template<typename T> struct add_cv<const T> : type_identity<const volatile T> {};
|
|
||||||
|
|
||||||
// specialization for volatile types
|
|
||||||
template<typename T> struct add_cv<volatile T> : type_identity<const volatile T> {};
|
|
||||||
|
|
||||||
// specialization for const volatile types
|
|
||||||
template<typename T> struct add_cv<const volatile T> : type_identity<const volatile T> {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -321,16 +303,7 @@ template<typename T> struct add_cv<const volatile T> : type_identity<const volat
|
|||||||
/// \details removes const and volatile from the provided type such that `const T`, `volatile T`, and
|
/// \details removes const and volatile from the provided type such that `const T`, `volatile T`, and
|
||||||
/// `const volatile T` become `T`
|
/// `const volatile T` become `T`
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct remove_cv : type_identity<T> {};
|
template<typename T> struct remove_cv : detail::_remove_cv<T> {};
|
||||||
|
|
||||||
// specialization for const types
|
|
||||||
template<typename T> struct remove_cv<const T> : type_identity<T> {};
|
|
||||||
|
|
||||||
// specialization for volatile types
|
|
||||||
template<typename T> struct remove_cv<volatile T> : type_identity<T> {};
|
|
||||||
|
|
||||||
// specialization for const volatile types
|
|
||||||
template<typename T> struct remove_cv<const volatile T> : type_identity<T> {};
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `typename remove_cv<T>::type`
|
/// \brief shorthand for `typename remove_cv<T>::type`
|
||||||
@@ -343,11 +316,11 @@ template<typename T> using remove_cv_t = typename remove_cv<T>::type;
|
|||||||
///
|
///
|
||||||
/// \details adds references and const volatile qualifiers to the provided type.
|
/// \details adds references and const volatile qualifiers to the provided type.
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct add_cvr : type_identity<add_reference_t<add_cv_t<T>>> {};
|
template<typename T> struct add_cvref : type_identity<add_reference_t<add_cv_t<T>>> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `typename add_cvr<T>::type`
|
/// \brief shorthand for `typename add_cvr<T>::type`
|
||||||
template<typename T> using add_cvr_t = typename add_cvr<T>::type;
|
template<typename T> using add_cvref_t = typename add_cvref<T>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -356,12 +329,12 @@ template<typename T> using add_cvr_t = typename add_cvr<T>::type;
|
|||||||
///
|
///
|
||||||
/// \details removes const and volatile from the provided type such that
|
/// \details removes const and volatile from the provided type such that
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct remove_cvr : type_identity<remove_cv_t<remove_reference_t<T>>> {};
|
template<typename T> struct remove_cvref : type_identity<remove_cv_t<remove_reference_t<T>>> {};
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `typename remove_cvr<T>::type`
|
/// \brief shorthand for `typename remove_cvr<T>::type`
|
||||||
template<typename T> using remove_cvr_t = typename remove_cvr<T>::type;
|
template<typename T> using remove_cvref_t = typename remove_cvref<T>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -370,12 +343,12 @@ template<typename T> using remove_cvr_t = typename remove_cvr<T>::type;
|
|||||||
///
|
///
|
||||||
/// \details removes const and volatile from the provided type such that
|
/// \details removes const and volatile from the provided type such that
|
||||||
/// \tparam T Reference Type
|
/// \tparam T Reference Type
|
||||||
template<typename T> struct remove_cvrp : type_identity<remove_cv_t<remove_reference_t<strip_pointers_t<T>>>> {};
|
template<typename T> struct remove_cvrefptr : type_identity<remove_cv_t<remove_reference_t<strip_pointers_t<T>>>> {};
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `typename remove_cvrp_t<T>::type`
|
/// \brief shorthand for `typename remove_cvrp_t<T>::type`
|
||||||
template<typename T> using remove_cvrp_t = typename remove_cvrp<T>::type;
|
template<typename T> using remove_cvrefptr_t = typename remove_cvrefptr<T>::type;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace fennec
|
|||||||
///
|
///
|
||||||
/// \brief check if \p T is a fennec::vector type
|
/// \brief check if \p T is a fennec::vector type
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_vector : detail::_is_vector_helper<remove_cvr_t<T>>{};
|
template<typename T> struct is_vector : detail::_is_vector_helper<remove_cvref_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_vector<T>::value```
|
/// \brief shorthand for ```is_vector<T>::value```
|
||||||
@@ -81,7 +81,7 @@ template<typename T> constexpr bool is_vector_v = is_vector<T>::value;
|
|||||||
///
|
///
|
||||||
/// \brief Get the number of Components in \p T, returns 1 for types that pass ```is_arithmetic<T>```, returns \ref vector::N for \ref vector "Vector" Types, and returns 0 for all other cases
|
/// \brief Get the number of Components in \p T, returns 1 for types that pass ```is_arithmetic<T>```, returns \ref vector::N for \ref vector "Vector" Types, and returns 0 for all other cases
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct component_count : detail::_component_count_helper<remove_cvr_t<T>>{};
|
template<typename T> struct component_count : detail::_component_count_helper<remove_cvref_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```component_count<T>::value```
|
/// \brief shorthand for ```component_count<T>::value```
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#define FENNEC_MEMORY_POINTERS_H
|
#define FENNEC_MEMORY_POINTERS_H
|
||||||
|
|
||||||
#include <fennec/lang/type_traits.h>
|
#include <fennec/lang/type_traits.h>
|
||||||
|
#include <fennec/lang/utility.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
@@ -176,6 +177,10 @@ public:
|
|||||||
return _handle;
|
return _handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator bool() const {
|
||||||
|
return _handle != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
delete_t _delete;
|
delete_t _delete;
|
||||||
|
|||||||
@@ -94,10 +94,7 @@ enum feature_ : uint32_t {
|
|||||||
|
|
||||||
using featureset_t = bitfield<feature_count>;
|
using featureset_t = bitfield<feature_count>;
|
||||||
using window_id = uint32_t;
|
using window_id = uint32_t;
|
||||||
using window_pool = object_pool<window*>;
|
using window_pool = object_pool<unique_ptr<window>>;
|
||||||
|
|
||||||
struct config {
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Public Members ======================================================================================================
|
// Public Members ======================================================================================================
|
||||||
@@ -115,11 +112,7 @@ enum feature_ : uint32_t {
|
|||||||
return features.test(feature);
|
return features.test(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual window* create_window(const window::config& conf) = 0;
|
virtual window* create_window(const window::config&, window* = nullptr) = 0;
|
||||||
|
|
||||||
window* get_window(size_t id) {
|
|
||||||
return id == window::nullid ? nullptr : windows[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void connect() = 0;
|
virtual void connect() = 0;
|
||||||
virtual void disconnect() = 0;
|
virtual void disconnect() = 0;
|
||||||
@@ -135,7 +128,6 @@ enum feature_ : uint32_t {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
featureset_t features;
|
featureset_t features;
|
||||||
window_pool windows;
|
|
||||||
unique_ptr<gfxcontext> gfx_context;
|
unique_ptr<gfxcontext> gfx_context;
|
||||||
|
|
||||||
FENNEC_RTTI_CLASS_ENABLE() {
|
FENNEC_RTTI_CLASS_ENABLE() {
|
||||||
|
|||||||
@@ -19,9 +19,10 @@
|
|||||||
#ifndef FENNEC_PLATFORM_INTERFACE_PLATFORM_H
|
#ifndef FENNEC_PLATFORM_INTERFACE_PLATFORM_H
|
||||||
#define FENNEC_PLATFORM_INTERFACE_PLATFORM_H
|
#define FENNEC_PLATFORM_INTERFACE_PLATFORM_H
|
||||||
|
|
||||||
#include <fennec/platform/interface/display_server.h>
|
|
||||||
#include <fennec/string/cstring.h>
|
#include <fennec/string/cstring.h>
|
||||||
|
|
||||||
|
#include <fennec/platform/window_manager.h>
|
||||||
|
|
||||||
#include <fennec/rtti/enable.h>
|
#include <fennec/rtti/enable.h>
|
||||||
#include <fennec/rtti/singleton.h>
|
#include <fennec/rtti/singleton.h>
|
||||||
#include <fennec/rtti/detail/_this_t.h>
|
#include <fennec/rtti/detail/_this_t.h>
|
||||||
@@ -79,10 +80,8 @@ public:
|
|||||||
virtual void initialize(); // Initialize Drivers and Contexts
|
virtual void initialize(); // Initialize Drivers and Contexts
|
||||||
virtual void shutdown(); // Close Drivers and Contexts
|
virtual void shutdown(); // Close Drivers and Contexts
|
||||||
|
|
||||||
display_server* get_display_server() { return display.get(); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unique_ptr<display_server> display;
|
unique_ptr<window_manager> wmanager;
|
||||||
|
|
||||||
FENNEC_RTTI_CLASS_ENABLE() {
|
FENNEC_RTTI_CLASS_ENABLE() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include <fennec/containers/bitfield.h>
|
#include <fennec/containers/bitfield.h>
|
||||||
#include <fennec/containers/optional.h>
|
#include <fennec/containers/optional.h>
|
||||||
|
#include <fennec/memory/pointers.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
@@ -112,20 +113,14 @@ public:
|
|||||||
double_t fractional_scaling;
|
double_t fractional_scaling;
|
||||||
};
|
};
|
||||||
|
|
||||||
window(display_server* server, size_t id, const config& conf)
|
window(display_server* server, const config& conf, window* parent);
|
||||||
: server(server), id(id)
|
|
||||||
, cfg(conf), state(), root(nullptr) {
|
|
||||||
state.mode = conf.mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~window() = default;
|
virtual ~window();
|
||||||
|
|
||||||
size_t get_id() const { return id; }
|
|
||||||
size_t get_parent_id() const { return cfg.parent; }
|
|
||||||
|
|
||||||
const config& get_config() const { return cfg; }
|
const config& get_config() const { return cfg; }
|
||||||
|
|
||||||
window* get_parent() const;
|
window* get_parent() const { return parent; }
|
||||||
|
window* get_root() const { return root; }
|
||||||
|
|
||||||
const ivec2& get_size() const { return state.rect.size; }
|
const ivec2& get_size() const { return state.rect.size; }
|
||||||
const ivec2& get_position() const { return state.rect.position; }
|
const ivec2& get_position() const { return state.rect.position; }
|
||||||
@@ -135,7 +130,6 @@ public:
|
|||||||
int get_pos_x() const { return state.rect.position.x; }
|
int get_pos_x() const { return state.rect.position.x; }
|
||||||
int get_pos_y() const { return state.rect.position.y; }
|
int get_pos_y() const { return state.rect.position.y; }
|
||||||
|
|
||||||
|
|
||||||
bool is_visible() const { return state.flags.test(state_visible); }
|
bool is_visible() const { return state.flags.test(state_visible); }
|
||||||
bool is_child() const { return state.flags.test(state_child); }
|
bool is_child() const { return state.flags.test(state_child); }
|
||||||
bool is_running() const { return state.flags.test(state_running); }
|
bool is_running() const { return state.flags.test(state_running); }
|
||||||
@@ -173,19 +167,19 @@ public:
|
|||||||
virtual void* get_native_handle() = 0;
|
virtual void* get_native_handle() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
display_server* const server;
|
display_server* const server;
|
||||||
const size_t id;
|
window* const parent;
|
||||||
config cfg;
|
config cfg;
|
||||||
state state;
|
state state;
|
||||||
window* root;
|
window* root;
|
||||||
gfxsurface* gfx_surface;
|
unique_ptr<gfxsurface> gfx_surface;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename DisplayT>
|
template<typename DisplayT>
|
||||||
class window_base : public window {
|
class window_base : public window {
|
||||||
public:
|
public:
|
||||||
window_base(display_server* display, size_t id, const config& conf)
|
window_base(display_server* display, const config& conf, window* parent)
|
||||||
: window(display, id, conf) {
|
: window(display, conf, parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
using display_t = DisplayT;
|
using display_t = DisplayT;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
|
|
||||||
void dispatch() override;
|
void dispatch() override;
|
||||||
|
|
||||||
window* create_window(const window::config& conf) override;
|
window* create_window(const window::config& conf, window* parent) override;
|
||||||
|
|
||||||
void* get_native_handle() override { return display; }
|
void* get_native_handle() override { return display; }
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace fennec
|
|||||||
|
|
||||||
class wayland_window : public window_base<wayland_server> {
|
class wayland_window : public window_base<wayland_server> {
|
||||||
public:
|
public:
|
||||||
wayland_window(display_server* server, uint32_t id, const config& cfg);
|
wayland_window(display_server* server, const config& cfg, window* parent);
|
||||||
~wayland_window();
|
~wayland_window();
|
||||||
|
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
|
|||||||
91
include/fennec/platform/window_manager.cpp
Normal file
91
include/fennec/platform/window_manager.cpp
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
#include <fennec/platform/window_manager.h>
|
||||||
|
|
||||||
|
#include <fennec/core/logger.h>
|
||||||
|
#include <fennec/platform/interface/platform.h>
|
||||||
|
#include <fennec/platform/interface/display_server.h>
|
||||||
|
#include <fennec/platform/interface/window.h>
|
||||||
|
|
||||||
|
namespace fennec {
|
||||||
|
|
||||||
|
window_manager::window_manager(platform* platform)
|
||||||
|
: _platform(platform) {
|
||||||
|
}
|
||||||
|
|
||||||
|
window_manager::~window_manager() {
|
||||||
|
shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_manager::initialize() {
|
||||||
|
if (_display) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the list of registered display servers
|
||||||
|
display_server::entrylist_t display_servers = display_server::get_type_list();
|
||||||
|
|
||||||
|
// Find first valid server
|
||||||
|
while (not display_servers.empty()) {
|
||||||
|
display_server::entry it = display_servers.front();
|
||||||
|
display_servers.pop();
|
||||||
|
|
||||||
|
unique_ptr<display_server> server = unique_ptr(it.ctor(_platform));
|
||||||
|
server->connect();
|
||||||
|
if (server->connected()) {
|
||||||
|
logger::log(format("Selected {} for the display server.", server->get_type().name()));
|
||||||
|
_display = move(server);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertf(_display, "Failed to select a display server!");
|
||||||
|
|
||||||
|
_thread = thread::current();
|
||||||
|
|
||||||
|
logger::log(format("Initializing Window Manager on thread: {:#016x}.", _thread));
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_manager::shutdown() {
|
||||||
|
if (not _display) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertf(_thread == thread::current(), "Attempted to shutdown Window Manager on a different thread!");
|
||||||
|
|
||||||
|
// Cleanup Windows
|
||||||
|
for (auto& window : _windows) {
|
||||||
|
window->shutdown();
|
||||||
|
window.reset();
|
||||||
|
}
|
||||||
|
_windows.clear();
|
||||||
|
|
||||||
|
// Cleanup Display Server
|
||||||
|
_display->disconnect();
|
||||||
|
_display.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_manager::dispatch() {
|
||||||
|
assertf(_thread == thread::current(), "Attempted to shutdown Window Manager on a different thread!");
|
||||||
|
|
||||||
|
_display->dispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // fennec
|
||||||
@@ -29,20 +29,52 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#ifndef FENNEC_PLATFORM_WINDOW_MANAGER_H
|
#ifndef FENNEC_PLATFORM_WINDOWMANAGER_H
|
||||||
#define FENNEC_PLATFORM_WINDOW_MANAGER_H
|
#define FENNEC_PLATFORM_WINDOWMANAGER_H
|
||||||
|
|
||||||
|
#include <fennec/platform/interface/fwd.h>
|
||||||
|
|
||||||
|
#include <fennec/memory/pointers.h>
|
||||||
|
#include <fennec/containers/object_pool.h>
|
||||||
|
#include <fennec/threading/thread.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Thread-Safe wrapper for `display_server` and `window`
|
|
||||||
class window_manager {
|
class window_manager {
|
||||||
|
// Definitions =========================================================================================================
|
||||||
|
private:
|
||||||
|
using server_t = unique_ptr<display_server>;
|
||||||
|
using window_t = unique_ptr<window>;
|
||||||
|
using window_pool_t = object_pool<window_t>;
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors & Destructor ===========================================================================================
|
||||||
public:
|
public:
|
||||||
|
window_manager(platform* platform);
|
||||||
|
~window_manager();
|
||||||
|
|
||||||
|
window_manager(const window_manager&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
// Thread-Specific Functions ===========================================================================================
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
void shutdown();
|
||||||
|
void dispatch();
|
||||||
|
|
||||||
|
|
||||||
|
// Thread-Safe Functions ===============================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
thread::id _thread;
|
||||||
|
platform* _platform;
|
||||||
|
server_t _display;
|
||||||
|
window_pool_t _windows;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // fennec
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_WINDOW_MANAGER_H
|
#endif // FENNEC_PLATFORM_WINDOWMANAGER_H
|
||||||
@@ -34,7 +34,6 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
class function;
|
|
||||||
struct vtypelist;
|
struct vtypelist;
|
||||||
template<typename...> struct typelist;
|
template<typename...> struct typelist;
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ private:
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static unique_ptr<type_data> _make_data() {
|
static unique_ptr<type_data> _make_data() {
|
||||||
using raw_t = remove_cvrp_t<T>;
|
using raw_t = remove_cvrefptr_t<T>;
|
||||||
using supers_t = detect_t<typelist<>, _super_class_list, T>;
|
using supers_t = detect_t<typelist<>, _super_class_list, T>;
|
||||||
|
|
||||||
auto res = fennec::unique_ptr<type_data>(new type_data{
|
auto res = fennec::unique_ptr<type_data>(new type_data{
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace fennec
|
|||||||
template<typename BaseT, typename...ArgsT>
|
template<typename BaseT, typename...ArgsT>
|
||||||
class type_registry {
|
class type_registry {
|
||||||
public:
|
public:
|
||||||
using ctor_t = BaseT* (*)(ArgsT&&...);
|
using ctor_t = BaseT* (*)(ArgsT...);
|
||||||
|
|
||||||
struct entry {
|
struct entry {
|
||||||
size_t priority;
|
size_t priority;
|
||||||
@@ -113,8 +113,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static BaseT* _constructor_helper(ArgsT&&...args) {
|
static BaseT* _constructor_helper(ArgsT...args) {
|
||||||
return new T(fennec::forward<ArgsT>(args)...);
|
return new T(args...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
454
include/fennec/threading/atomic.h
Normal file
454
include/fennec/threading/atomic.h
Normal file
@@ -0,0 +1,454 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file atomic.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_THREADING_ATOMIC_H
|
||||||
|
#define FENNEC_THREADING_ATOMIC_H
|
||||||
|
|
||||||
|
#include <fennec/threading/detail/_atomic.h>
|
||||||
|
|
||||||
|
#include <fennec/lang/type_traits.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
using ::memory_order;
|
||||||
|
using ::memory_order_relaxed;
|
||||||
|
using ::memory_order_consume;
|
||||||
|
using ::memory_order_acquire;
|
||||||
|
using ::memory_order_release;
|
||||||
|
using ::memory_order_acq_rel;
|
||||||
|
using ::memory_order_seq_cst;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Wrapper for atomic variables
|
||||||
|
/// \tparam T The type of the atomic variable
|
||||||
|
template<typename T>
|
||||||
|
struct atomic {
|
||||||
|
|
||||||
|
// Assertions ==========================================================================================================
|
||||||
|
public:
|
||||||
|
static_assert(is_integral_v<T>, "fennec::atomic not defined for the provided type. Default implementation"
|
||||||
|
"only supports integral types.");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Definitions =========================================================================================================
|
||||||
|
public:
|
||||||
|
using value_t = T;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors ========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Constructor
|
||||||
|
///
|
||||||
|
/// \details Initializes the held atomic variable with `0`.
|
||||||
|
constexpr atomic() noexcept
|
||||||
|
: _value(static_cast<T>(0)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Value Constructor
|
||||||
|
///
|
||||||
|
/// \details Initializes the held atomic variable with `value`.
|
||||||
|
/// \param value The value to initialize the atomic variable with.
|
||||||
|
constexpr atomic(const T value) noexcept
|
||||||
|
: _value(value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic(const atomic&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Assignment ==========================================================================================================
|
||||||
|
|
||||||
|
atomic& operator=(const atomic&) = delete;
|
||||||
|
atomic& operator=(const atomic&) volatile = delete;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Atomically assigns `x` to the atomic variable.
|
||||||
|
/// \param x The value to assign
|
||||||
|
/// \returns `x`
|
||||||
|
T operator=(const T x) noexcept {
|
||||||
|
this->store(x);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Stores a value into an atomic object
|
||||||
|
///
|
||||||
|
/// \details Atomically assigns `x` to the atomic variable.
|
||||||
|
/// \param x The value to assign
|
||||||
|
/// \returns `x`
|
||||||
|
T operator=(const T x) volatile noexcept {
|
||||||
|
this->store(x);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Modifiers ===========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Atomically replaces the current value with `x`. Memory is affected according to the value of `order`.
|
||||||
|
/// \param x The value to store into the atomic variable
|
||||||
|
/// \param order Memory order constraints to enforce
|
||||||
|
void store(const T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
|
::atomic_store_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Atomically replaces the value of the atomic object with a non-atomic argument
|
||||||
|
///
|
||||||
|
/// \details Atomically replaces the current value with `x`. Memory is affected according to the value of `order`.
|
||||||
|
/// \param x The value to store into the atomic variable
|
||||||
|
/// \param order Memory order constraints to enforce
|
||||||
|
void store(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
|
::atomic_store_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Atomically loads and returns the current value of the atomic variable.
|
||||||
|
/// Memory is affected according to the value of `order`.
|
||||||
|
/// \param order Memory order constraints to enforce
|
||||||
|
/// \returns The current value of the atomic variable.
|
||||||
|
T load(memory_order order = memory_order_seq_cst) const noexcept {
|
||||||
|
return ::atomic_load_explicit(&_value, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Atomically obtains the value of the atomic object
|
||||||
|
///
|
||||||
|
/// \details Atomically loads and returns the current value of the atomic variable.
|
||||||
|
/// Memory is affected according to the value of `order`.
|
||||||
|
/// \param order Memory order constraints to enforce
|
||||||
|
/// \returns The current value of the atomic variable.
|
||||||
|
T load(memory_order order = memory_order_seq_cst) const volatile noexcept {
|
||||||
|
return ::atomic_load_explicit(&_value, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Atomically loads and returns the current value of the atomic variable. Equivalent to `load()`.
|
||||||
|
operator T() const noexcept {
|
||||||
|
return load();
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Loads a value from an atomic object
|
||||||
|
///
|
||||||
|
/// \details Atomically loads and returns the current value of the atomic variable. Equivalent to `load()`.
|
||||||
|
operator T() const volatile noexcept {
|
||||||
|
return load();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Atomically replaces the underlying value with `x` (a read-modify-write operation).
|
||||||
|
/// Memory is affected according to the value of `order`.
|
||||||
|
/// \param x Value to assign
|
||||||
|
/// \param order Memory order constraints to enforce
|
||||||
|
/// \return The value of the atomic variable before the call.
|
||||||
|
T exchange(const T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
|
return ::atomic_exchange_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Atomically replaces the value of the atomic object and obtains the value held previously
|
||||||
|
///
|
||||||
|
/// \details Atomically replaces the underlying value with `x` (a read-modify-write operation).
|
||||||
|
/// Memory is affected according to the value of `order`.
|
||||||
|
/// \param x Value to assign
|
||||||
|
/// \param order Memory order constraints to enforce
|
||||||
|
/// \return The value of the atomic variable before the call.
|
||||||
|
T exchange(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
|
return ::atomic_exchange_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Atomically compares the value of `*this` with that of `exp`.
|
||||||
|
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
||||||
|
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
||||||
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
|
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
||||||
|
bool compare_exchange_weak(T& exp, T x, memory_order succ, memory_order fail) noexcept {
|
||||||
|
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, succ, fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Atomically compares the value of `*this` with that of `exp`.
|
||||||
|
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
||||||
|
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
||||||
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
|
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
||||||
|
bool compare_exchange_weak(T& exp, T x, memory_order succ, memory_order fail) volatile noexcept {
|
||||||
|
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, succ, fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Atomically compares the value of `*this` with that of `exp`.
|
||||||
|
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
||||||
|
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
||||||
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
|
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
||||||
|
bool compare_exchange_weak(T& exp, T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
|
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, order, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not
|
||||||
|
///
|
||||||
|
/// \details Atomically compares the value of `*this` with that of `exp`.
|
||||||
|
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
||||||
|
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
||||||
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
|
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
||||||
|
bool compare_exchange_weak(T& exp, T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
|
return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, order, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Atomically compares the value of `*this` with that of `exp`.
|
||||||
|
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
||||||
|
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
||||||
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
|
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
||||||
|
bool compare_exchange_strong(T& exp, T x, memory_order succ, memory_order fail) noexcept {
|
||||||
|
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, succ, fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Atomically compares the value of `*this` with that of `exp`.
|
||||||
|
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
||||||
|
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
||||||
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
|
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
||||||
|
bool compare_exchange_strong(T& exp, T x, memory_order succ, memory_order fail) volatile noexcept {
|
||||||
|
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, succ, fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Atomically compares the value of `*this` with that of `exp`.
|
||||||
|
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
||||||
|
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
||||||
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
|
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
||||||
|
bool compare_exchange_strong(T& exp, T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
|
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, order, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Atomically compares the value of the atomic object with non-atomic argument and performs atomic exchange if equal or atomic load if not
|
||||||
|
///
|
||||||
|
/// \details Atomically compares the value of `*this` with that of `exp`.
|
||||||
|
/// If they are equal, replaces the former with `x` (performs read-modify-write operation).
|
||||||
|
/// Otherwise, loads the actual value stored in *this into `exp` (performs load operation).
|
||||||
|
/// \param exp Reference to the value expected to be found in the atomic object.
|
||||||
|
/// \param x The value to store in the atomic object if it is as expected.
|
||||||
|
/// \param succ The memory synchronization ordering for the read-modify-write operation if the comparison succeeds.
|
||||||
|
/// \param fail The memory synchronization ordering for the load operation if the comparison fails.
|
||||||
|
/// \param order The memory synchronization ordering for both operations.
|
||||||
|
/// \returns `true` if the underlying atomic value was successfully changed, `false` otherwise.
|
||||||
|
bool compare_exchange_strong(T& exp, T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
|
return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, order, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Operations ==========================================================================================================
|
||||||
|
|
||||||
|
T fetch_add(const T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
|
return ::atomic_fetch_add_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
T fetch_add(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
|
return ::atomic_fetch_add_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator+=(const T x) noexcept {
|
||||||
|
return this->fetch_add(x) + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator+=(const T x) volatile noexcept {
|
||||||
|
return this->fetch_add(x) + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
T operator++() noexcept {
|
||||||
|
return this->fetch_add(1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator++() volatile noexcept {
|
||||||
|
return this->fetch_add(1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator++(int) noexcept {
|
||||||
|
return this->fetch_add(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator++(int) volatile noexcept {
|
||||||
|
return this->fetch_add(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
T fetch_sub(const T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
|
return ::atomic_fetch_sub_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
T fetch_sub(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
|
return ::atomic_fetch_sub_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator-=(const T x) noexcept {
|
||||||
|
return this->fetch_sub(x) - x;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator-=(const T x) volatile noexcept {
|
||||||
|
return this->fetch_sub(x) - x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
T operator--() noexcept {
|
||||||
|
return this->fetch_sub(1) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator--() volatile noexcept {
|
||||||
|
return this->fetch_sub(1) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator--(int) noexcept {
|
||||||
|
return this->fetch_sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator--(int) volatile noexcept {
|
||||||
|
return this->fetch_sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Bit Operations ======================================================================================================
|
||||||
|
|
||||||
|
T fetch_and(const T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
|
return ::atomic_fetch_and_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
T fetch_and(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
|
return ::atomic_fetch_and_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator&=(const T x) noexcept {
|
||||||
|
return this->fetch_and(x) & x;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator&=(const T x) volatile noexcept {
|
||||||
|
return this->fetch_and(x) & x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
T fetch_or(const T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
|
return ::atomic_fetch_or_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
T fetch_or(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
|
return ::atomic_fetch_or_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator|=(const T x) noexcept {
|
||||||
|
return this->fetch_or(x) & x;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator|=(const T x) volatile noexcept {
|
||||||
|
return this->fetch_or(x) & x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
T fetch_xor(const T x, memory_order order = memory_order_seq_cst) noexcept {
|
||||||
|
return ::atomic_fetch_xor_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
T fetch_xor(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
|
||||||
|
return ::atomic_fetch_xor_explicit(&_value, x, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator^=(const T x) noexcept {
|
||||||
|
return this->fetch_xor(x) & x;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator^=(const T x) volatile noexcept {
|
||||||
|
return this->fetch_xor(x) & x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
_Atomic T _value;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_THREADING_ATOMIC_H
|
||||||
222
include/fennec/threading/detail/_atomic.h
Normal file
222
include/fennec/threading/detail/_atomic.h
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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_LANG_DETAIL_ATOMIC_H
|
||||||
|
#define FENNEC_LANG_DETAIL_ATOMIC_H
|
||||||
|
|
||||||
|
// Define _Atomic as volatile
|
||||||
|
#ifdef _Atomic
|
||||||
|
#undef _Atomic
|
||||||
|
#endif
|
||||||
|
#define _Atomic volatile
|
||||||
|
|
||||||
|
#if FENNEC_COMPILER_GCC
|
||||||
|
|
||||||
|
// memory_order ========================================================================================================
|
||||||
|
|
||||||
|
enum memory_order {
|
||||||
|
memory_order_relaxed = __ATOMIC_RELAXED,
|
||||||
|
memory_order_consume = __ATOMIC_CONSUME,
|
||||||
|
memory_order_acquire = __ATOMIC_ACQUIRE,
|
||||||
|
memory_order_release = __ATOMIC_RELEASE,
|
||||||
|
memory_order_acq_rel = __ATOMIC_ACQ_REL,
|
||||||
|
memory_order_seq_cst = __ATOMIC_SEQ_CST,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_init =========================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr void atomic_init(_Atomic T* x, const T val) {
|
||||||
|
*x = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_flag =========================================================================================================
|
||||||
|
|
||||||
|
struct atomic_flag;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_flag_test_and_set ============================================================================================
|
||||||
|
|
||||||
|
constexpr bool atomic_flag_test_and_set(_Atomic atomic_flag* x) {
|
||||||
|
return ::__atomic_test_and_set(x, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool atomic_flag_test_and_set_explicit(_Atomic atomic_flag* x, memory_order memorder) {
|
||||||
|
return ::__atomic_test_and_set(x, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_flag_clear ===================================================================================================
|
||||||
|
|
||||||
|
constexpr void atomic_flag_clear(_Atomic atomic_flag* x) {
|
||||||
|
return ::__atomic_clear(x, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void atomic_flag_clear_explicit(_Atomic atomic_flag* x, memory_order memorder) {
|
||||||
|
return ::__atomic_clear(x, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_load =========================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_load(_Atomic T* x) {
|
||||||
|
return ::__atomic_load_n(x, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_load_explicit(_Atomic T* x, memory_order memorder) {
|
||||||
|
return ::__atomic_load_n(x, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_store ========================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool atomic_store(_Atomic T* x, const T val) {
|
||||||
|
return ::__atomic_store_n(x, val, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool atomic_store_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
||||||
|
return ::__atomic_store_n(x, val, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_exchange =====================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool atomic_exchange(_Atomic T* x, const T val) {
|
||||||
|
return ::__atomic_exchange_n(x, val, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool atomic_exchange_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
||||||
|
return ::__atomic_exchange_n(x, val, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_compare_exchange_weak ========================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool atomic_compare_exchange_weak(_Atomic T* x, T* exp, const T des) {
|
||||||
|
return ::__atomic_compare_exchange_n(x, exp, des, true, memory_order_seq_cst, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool atomic_compare_exchange_weak_explicit(_Atomic T* x, T* exp, const T des, memory_order succ, memory_order fail) {
|
||||||
|
return ::__atomic_compare_exchange_n(x, exp, des, true, succ, fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_compare_exchange_strong ======================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool atomic_compare_exchange_strong(_Atomic T* x, T* exp, const T des) {
|
||||||
|
return ::__atomic_compare_exchange_n(x, exp, des, false, memory_order_seq_cst, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool atomic_compare_exchange_strong_explicit(_Atomic T* x, T* exp, const T des, memory_order succ, memory_order fail) {
|
||||||
|
return ::__atomic_compare_exchange_n(x, exp, des, false, succ, fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_fetch_add ====================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_fetch_add(_Atomic T* x, const T val) {
|
||||||
|
return ::__atomic_fetch_add(x, val, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_fetch_add_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
||||||
|
return ::__atomic_fetch_add(x, val, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_fetch_sub ====================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_fetch_sub(_Atomic T* x, const T val) {
|
||||||
|
return ::__atomic_fetch_sub(x, val, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_fetch_sub_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
||||||
|
return ::__atomic_fetch_sub(x, val, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_fetch_or ====================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_fetch_or(_Atomic T* x, const T val) {
|
||||||
|
return ::__atomic_fetch_or(x, val, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_fetch_or_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
||||||
|
return ::__atomic_fetch_or(x, val, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_fetch_xor ====================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_fetch_xor(_Atomic T* x, const T val) {
|
||||||
|
return ::__atomic_fetch_xor(x, val, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_fetch_xor_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
||||||
|
return ::__atomic_fetch_xor(x, val, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// atomic_fetch_and ====================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_fetch_and(_Atomic T* x, const T val) {
|
||||||
|
return ::__atomic_fetch_and(x, val, memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T atomic_fetch_and_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
||||||
|
return ::__atomic_fetch_and(x, val, memorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // FENNEC_LANG_DETAIL_ATOMIC_H
|
||||||
59
include/fennec/threading/detail/_thread.h
Normal file
59
include/fennec/threading/detail/_thread.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file _thread.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_THREADING_DETAIL_THREAD_H
|
||||||
|
#define FENNEC_THREADING_DETAIL_THREAD_H
|
||||||
|
|
||||||
|
#include <fennec/containers/tuple.h>
|
||||||
|
#include <fennec/lang/function.h>
|
||||||
|
#include <fennec/memory/pointers.h>
|
||||||
|
|
||||||
|
namespace fennec::detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename FuncT, typename...ArgsT> using thread_proxy_t = tuple<FuncT, ArgsT...>;
|
||||||
|
|
||||||
|
template<typename FuncT, typename...ArgsT, size_t...I>
|
||||||
|
void _execute_thread(thread_proxy_t<function<FuncT>, ArgsT...>& data, index_metasequence<I...>) {
|
||||||
|
auto func = data.template get<0>();
|
||||||
|
func(fennec::move(data.template get<I + 1>()) ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DataT>
|
||||||
|
void* _run_thread(void* data) {
|
||||||
|
unique_ptr<DataT> ptr(data);
|
||||||
|
detail::_execute_thread(*ptr, make_index_metasequence_t<DataT::size - 1>{});
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_THREADING_DETAIL_THREAD_H
|
||||||
171
include/fennec/threading/thread.h
Normal file
171
include/fennec/threading/thread.h
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file thread.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_THREADING_THREAD_H
|
||||||
|
#define FENNEC_THREADING_THREAD_H
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <fennec/format/formatter.h>
|
||||||
|
#include <fennec/lang/type_traits.h>
|
||||||
|
#include <fennec/lang/type_transforms.h>
|
||||||
|
#include <fennec/memory/bytes.h>
|
||||||
|
#include <fennec/threading/detail/_thread.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
class thread {
|
||||||
|
private:
|
||||||
|
static constexpr pthread_t nullthread = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using native_handle_type = pthread_t;
|
||||||
|
|
||||||
|
class id {
|
||||||
|
public:
|
||||||
|
constexpr id() noexcept : _id(0) {}
|
||||||
|
|
||||||
|
constexpr friend bool operator==(id x, id y) noexcept {
|
||||||
|
if (x._id == 0) {
|
||||||
|
return y._id == 0;
|
||||||
|
}
|
||||||
|
if (y._id == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return pthread_equal(x._id, y._id) != 0;
|
||||||
|
}
|
||||||
|
constexpr friend bool operator!=(id x, id y) noexcept { return !(x == y); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class thread;
|
||||||
|
friend struct hash<id>;
|
||||||
|
friend struct formatter<id>;
|
||||||
|
|
||||||
|
constexpr id(pthread_t id) : _id(id) {}
|
||||||
|
|
||||||
|
pthread_t _id;
|
||||||
|
};
|
||||||
|
|
||||||
|
thread() noexcept
|
||||||
|
: _handle(nullthread) {
|
||||||
|
}
|
||||||
|
|
||||||
|
thread(thread&& th)
|
||||||
|
: _handle(th._handle) {
|
||||||
|
th._handle = nullthread;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread(const thread&) = delete;
|
||||||
|
|
||||||
|
template<typename FuncT, typename...ArgsT>
|
||||||
|
requires(not is_same_v<thread, remove_cvref_t<FuncT>>)
|
||||||
|
thread(FuncT&& func, ArgsT&&...args)
|
||||||
|
: _handle(nullthread) {
|
||||||
|
using proxy_t = detail::thread_proxy_t<function<FuncT>, ArgsT...>;
|
||||||
|
unique_ptr<proxy_t> proxy = fennec::make_unique<proxy_t>(fennec::forward<FuncT>(func), fennec::forward<ArgsT>(args)...);
|
||||||
|
|
||||||
|
int_t res = ::pthread_create(&_handle, nullptr, &detail::_run_thread<proxy_t>(), proxy.get());
|
||||||
|
assertf(res == 0, "Thread creation failed!");
|
||||||
|
|
||||||
|
proxy.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
thread& operator=(thread&& th) noexcept {
|
||||||
|
assertf(_handle == nullthread, "Attempted to overwrite running thread!");
|
||||||
|
|
||||||
|
_handle = th._handle;
|
||||||
|
th._handle = nullthread;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~thread() {
|
||||||
|
assertf(_handle == 0, "Attempted to destruct a running thread!");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool joinable() const noexcept {
|
||||||
|
return _handle != nullthread and pthread_self() != _handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void join() {
|
||||||
|
if (not joinable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_t res = pthread_join(_handle, nullptr);
|
||||||
|
assertf(res == 0, "Failed to join thread!");
|
||||||
|
_handle = nullthread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void detatch() {
|
||||||
|
if (not joinable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_t res = pthread_detach(_handle);
|
||||||
|
assertf(res == 0, "Failed to detatch thread!");
|
||||||
|
_handle = nullthread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(thread& other) {
|
||||||
|
fennec::swap(_handle, other._handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static id current() {
|
||||||
|
return pthread_self();
|
||||||
|
}
|
||||||
|
|
||||||
|
id get_id() const {
|
||||||
|
return _handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
pthread_t _handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hash<thread::id> {
|
||||||
|
size_t operator()(thread::id v) const noexcept {
|
||||||
|
return hash<thread::native_handle_type>()(v._id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct formatter<thread::id> {
|
||||||
|
string operator()(const format_arg& fmt, thread::id v) const noexcept {
|
||||||
|
return formatter<thread::native_handle_type>()(fmt, v._id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_THREADING_THREAD_H
|
||||||
@@ -1047,6 +1047,7 @@ void file::println(const cstring& str) {
|
|||||||
|
|
||||||
void file::println(const string& str) {
|
void file::println(const string& str) {
|
||||||
write(str.data(), str.length());
|
write(str.data(), str.length());
|
||||||
|
putc('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool file::putc(char c) {
|
bool file::putc(char c) {
|
||||||
|
|||||||
@@ -29,25 +29,22 @@ platform::platform() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void platform::initialize() {
|
void platform::initialize() {
|
||||||
|
if (wmanager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
logger::log(format("Initializing platform {}", get_type().name()));
|
logger::log(format("Initializing platform {}", get_type().name()));
|
||||||
|
|
||||||
display_server::entrylist_t display_servers = display_server::get_type_list();
|
// Setup Window Manager
|
||||||
while (not display_servers.empty()) {
|
wmanager = make_unique<window_manager>(this);
|
||||||
display_server::entry it = display_servers.front();
|
wmanager->initialize();
|
||||||
display_servers.pop();
|
|
||||||
|
|
||||||
unique_ptr<display_server> server = unique_ptr(it.ctor(this));
|
|
||||||
server->connect();
|
|
||||||
if (server->connected()) {
|
|
||||||
logger::log(format("Selected {} for the display server.", server->get_type().name()));
|
|
||||||
display = move(server);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform::shutdown() {
|
void platform::shutdown() {
|
||||||
display.reset();
|
|
||||||
|
// Cleanup Window Manager
|
||||||
|
wmanager->shutdown();
|
||||||
|
wmanager.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,14 +29,20 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
#include <fennec/platform/interface/window.h>
|
#include <fennec/platform/interface/window.h>
|
||||||
#include <fennec/platform/interface/display_server.h>
|
|
||||||
#include <fennec/renderers/interface/gfxsurface.h>
|
#include <fennec/renderers/interface/gfxsurface.h>
|
||||||
|
#include <fennec/platform/interface/display_server.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
window* window::get_parent() const {
|
window::window(display_server* server, const config& conf, window* parent)
|
||||||
return server->get_window(cfg.parent);
|
: server(server), parent(parent)
|
||||||
|
, cfg(conf), state(), root(nullptr) {
|
||||||
|
state.mode = conf.mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
window::~window() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void window::begin_frame() {
|
void window::begin_frame() {
|
||||||
|
|||||||
@@ -177,9 +177,8 @@ void wayland_server::dispatch() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window* wayland_server::create_window(const window::config& conf) {
|
window* wayland_server::create_window(const window::config& conf, window* parent) {
|
||||||
size_t id = windows.insert(new wayland_window(this, windows.next_id(), conf));
|
return new wayland_window(this, conf, parent);
|
||||||
return windows[id];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wayland_server::_wl_registry_listen_global(void* data, wl_registry* reg, uint32_t id, const char* name, uint32_t version) {
|
void wayland_server::_wl_registry_listen_global(void* data, wl_registry* reg, uint32_t id, const char* name, uint32_t version) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <fennec/math/relational.h>
|
#include <fennec/math/relational.h>
|
||||||
#include <fennec/platform/interface/display_server.h>
|
#include <fennec/platform/interface/display_server.h>
|
||||||
|
|
||||||
|
#include <fennec/renderers/interface/gfxsurface.h>
|
||||||
#include <fennec/renderers/interface/gfxcontext.h>
|
#include <fennec/renderers/interface/gfxcontext.h>
|
||||||
|
|
||||||
#include <fennec/platform/linux/wayland/server.h>
|
#include <fennec/platform/linux/wayland/server.h>
|
||||||
@@ -27,7 +28,6 @@
|
|||||||
#include <fennec/platform/linux/wayland/lib/wayland.h>
|
#include <fennec/platform/linux/wayland/lib/wayland.h>
|
||||||
#include <fennec/platform/linux/wayland/lib/headers/xdg-shell-client-protocols.h>
|
#include <fennec/platform/linux/wayland/lib/headers/xdg-shell-client-protocols.h>
|
||||||
#include <fennec/platform/linux/wayland/libdecor/libdecor.h>
|
#include <fennec/platform/linux/wayland/libdecor/libdecor.h>
|
||||||
#include <fennec/renderers/interface/gfxsurface.h>
|
|
||||||
|
|
||||||
#if FENNEC_HAS_LIBDECOR
|
#if FENNEC_HAS_LIBDECOR
|
||||||
#include <fennec/platform/linux/wayland/libdecor/libdecor.h>
|
#include <fennec/platform/linux/wayland/libdecor/libdecor.h>
|
||||||
@@ -35,11 +35,10 @@
|
|||||||
|
|
||||||
using namespace fennec;
|
using namespace fennec;
|
||||||
|
|
||||||
wayland_window::wayland_window(display_server* server, uint32_t id, const config& cfg)
|
wayland_window::wayland_window(display_server* server, const config& cfg, window* parent)
|
||||||
: window_base(server, id, cfg)
|
: window_base(server, cfg, parent)
|
||||||
, surface(nullptr)
|
, surface(nullptr)
|
||||||
, xdgsurface(nullptr) {
|
, xdgsurface(nullptr) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wayland_window::~wayland_window() {
|
wayland_window::~wayland_window() {
|
||||||
@@ -79,7 +78,7 @@ void wayland_window::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wayland_window* root = this;
|
root = parent;
|
||||||
while (root != nullptr and root->is_popup()) {
|
while (root != nullptr and root->is_popup()) {
|
||||||
root = static_cast<wayland_window*>(root->get_parent());
|
root = static_cast<wayland_window*>(root->get_parent());
|
||||||
}
|
}
|
||||||
@@ -110,7 +109,7 @@ void wayland_window::initialize() {
|
|||||||
.reserved9 = nullptr,
|
.reserved9 = nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
gfx_surface = wl_server->get_gfx_context()->create_surface(this);
|
gfx_surface = unique_ptr(wl_server->get_gfx_context()->create_surface(this));
|
||||||
|
|
||||||
if (wl_server->has_libdecor) {
|
if (wl_server->has_libdecor) {
|
||||||
|
|
||||||
@@ -151,11 +150,6 @@ void wayland_window::shutdown() {
|
|||||||
|
|
||||||
wayland_server* wl_server = static_cast<wayland_server*>(server);
|
wayland_server* wl_server = static_cast<wayland_server*>(server);
|
||||||
|
|
||||||
if (frame_callback) {
|
|
||||||
wl_callback_destroy(frame_callback);
|
|
||||||
frame_callback = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FENNEC_HAS_LIBDECOR
|
#if FENNEC_HAS_LIBDECOR
|
||||||
if (libdecorframe) {
|
if (libdecorframe) {
|
||||||
libdecor_frame_unref(libdecorframe);
|
libdecor_frame_unref(libdecorframe);
|
||||||
@@ -164,6 +158,15 @@ void wayland_window::shutdown() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (gfx_surface) {
|
||||||
|
gfx_surface.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame_callback) {
|
||||||
|
wl_callback_destroy(frame_callback);
|
||||||
|
frame_callback = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (xdgtoplevel) {
|
if (xdgtoplevel) {
|
||||||
xdg_toplevel_destroy(xdgtoplevel);
|
xdg_toplevel_destroy(xdgtoplevel);
|
||||||
xdgtoplevel = nullptr;
|
xdgtoplevel = nullptr;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ set(CMAKE_C_STANDARD 23)
|
|||||||
add_executable(fennec-test
|
add_executable(fennec-test
|
||||||
main.cpp
|
main.cpp
|
||||||
tests/lang/test_metaprogramming.h
|
tests/lang/test_metaprogramming.h
|
||||||
|
tests/lang/test_function.h
|
||||||
|
tests/test_threading.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(fennec-test PUBLIC FENNEC_TEST_CWD="${CMAKE_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME}"
|
target_compile_definitions(fennec-test PUBLIC FENNEC_TEST_CWD="${CMAKE_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME}"
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "tests/test_filesystem.h"
|
#include "tests/test_filesystem.h"
|
||||||
#include "tests/test_platform.h"
|
#include "tests/test_platform.h"
|
||||||
#include "tests/test_rtti.h"
|
#include "tests/test_rtti.h"
|
||||||
|
#include "tests/test_threading.h"
|
||||||
|
|
||||||
int main(int, char **)
|
int main(int, char **)
|
||||||
{
|
{
|
||||||
@@ -66,9 +67,9 @@ int main(int, char **)
|
|||||||
fennec::test::fennec_test_filesystem();
|
fennec::test::fennec_test_filesystem();
|
||||||
fennec_test_spacer(3);
|
fennec_test_spacer(3);
|
||||||
|
|
||||||
fennec_test_header("platform library");
|
fennec_test_header("threading");
|
||||||
fennec_test_spacer(2);
|
fennec_test_spacer(2);
|
||||||
fennec::test::fennec_test_platform();
|
fennec::test::fennec_test_threading();
|
||||||
fennec_test_spacer(3);
|
fennec_test_spacer(3);
|
||||||
|
|
||||||
fennec_test_header("rtti library");
|
fennec_test_header("rtti library");
|
||||||
@@ -76,5 +77,10 @@ int main(int, char **)
|
|||||||
fennec::test::fennec_test_rtti();
|
fennec::test::fennec_test_rtti();
|
||||||
fennec_test_spacer(3);
|
fennec_test_spacer(3);
|
||||||
|
|
||||||
|
fennec_test_header("platform library");
|
||||||
|
fennec_test_spacer(2);
|
||||||
|
fennec::test::fennec_test_platform();
|
||||||
|
fennec_test_spacer(3);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
64
test/tests/lang/test_function.h
Normal file
64
test/tests/lang/test_function.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file test_function.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_TEST_LANG_FUNCTION_H
|
||||||
|
#define FENNEC_TEST_LANG_FUNCTION_H
|
||||||
|
|
||||||
|
#include "../../test.h"
|
||||||
|
|
||||||
|
#include <fennec/lang/function.h>
|
||||||
|
|
||||||
|
namespace fennec::test
|
||||||
|
{
|
||||||
|
|
||||||
|
inline bool fennec_test_lang_function_test() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void fennec_test_lang_function() {
|
||||||
|
function<bool()> test;
|
||||||
|
|
||||||
|
fennec_test_run((bool)(test = fennec_test_lang_function_test), true);
|
||||||
|
fennec_test_run(test(), true);
|
||||||
|
|
||||||
|
fennec_test_spacer(1);
|
||||||
|
|
||||||
|
fennec_test_run((bool)(test = []() { return true; }), true);
|
||||||
|
fennec_test_run(test(), true);
|
||||||
|
|
||||||
|
fennec_test_spacer(1);
|
||||||
|
|
||||||
|
fennec_test_run((bool)(test = nullptr), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_TEST_LANG_FUNCTION_H
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "lang/test_bits.h"
|
#include "lang/test_bits.h"
|
||||||
#include "lang/test_conditional_types.h"
|
#include "lang/test_conditional_types.h"
|
||||||
|
#include "lang/test_function.h"
|
||||||
#include "lang/test_hashing.h"
|
#include "lang/test_hashing.h"
|
||||||
#include "lang/test_metaprogramming.h"
|
#include "lang/test_metaprogramming.h"
|
||||||
|
|
||||||
@@ -41,6 +42,11 @@ namespace fennec::test
|
|||||||
fennec_test_subheader("metaprogramming tests");
|
fennec_test_subheader("metaprogramming tests");
|
||||||
fennec_test_spacer(2);
|
fennec_test_spacer(2);
|
||||||
fennec_test_lang_metaprogramming();
|
fennec_test_lang_metaprogramming();
|
||||||
|
fennec_test_spacer(3);
|
||||||
|
|
||||||
|
fennec_test_subheader("function tests");
|
||||||
|
fennec_test_spacer(2);
|
||||||
|
fennec_test_lang_function();
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ inline void fennec_test_platform() {
|
|||||||
platform* platform = platform::instance();
|
platform* platform = platform::instance();
|
||||||
platform->initialize();
|
platform->initialize();
|
||||||
|
|
||||||
|
/*
|
||||||
display_server* display = platform->get_display_server();
|
display_server* display = platform->get_display_server();
|
||||||
|
|
||||||
window* window = display->create_window(window::config {
|
window* window = display->create_window(window::config {
|
||||||
@@ -59,8 +60,7 @@ inline void fennec_test_platform() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window->shutdown();
|
window->shutdown();
|
||||||
|
*/
|
||||||
delete window;
|
|
||||||
|
|
||||||
platform::instance()->shutdown();
|
platform::instance()->shutdown();
|
||||||
|
|
||||||
|
|||||||
48
test/tests/test_threading.h
Normal file
48
test/tests/test_threading.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file test_threading.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FENNEC_TEST_THREADING_H
|
||||||
|
#define FENNEC_TEST_THREADING_H
|
||||||
|
|
||||||
|
#include <fennec/threading/atomic.h>
|
||||||
|
|
||||||
|
namespace fennec::test
|
||||||
|
{
|
||||||
|
|
||||||
|
inline void fennec_test_threading() {
|
||||||
|
|
||||||
|
atomic<bool> test;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_TEST_THREADING_H
|
||||||
Reference in New Issue
Block a user