diff --git a/docs/prj/Chevron_diagrams.drawio b/docs/prj/Chevron_diagrams.drawio index d9f7d0b..8a767a5 100644 --- a/docs/prj/Chevron_diagrams.drawio +++ b/docs/prj/Chevron_diagrams.drawio @@ -609,7 +609,7 @@ - + @@ -639,24 +639,30 @@ - + - + - + - + + + + + + + - + @@ -682,7 +688,7 @@ - + @@ -690,7 +696,7 @@ - + @@ -786,7 +792,7 @@ - + @@ -888,7 +894,7 @@ - + @@ -987,7 +993,7 @@ - + @@ -1331,11 +1337,11 @@ - - + + - + @@ -1413,7 +1419,7 @@ - + @@ -1500,7 +1506,7 @@ - + @@ -1644,7 +1650,7 @@ - + @@ -1652,13 +1658,13 @@ - - + + - + @@ -1685,7 +1691,7 @@ - + @@ -1733,7 +1739,7 @@ - + @@ -1784,7 +1790,7 @@ - + @@ -1954,8 +1960,8 @@ - - + + @@ -1986,7 +1992,7 @@ - + @@ -2074,6 +2080,704 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/prj/resources/Hoard - A Scalable Memory Allocator for Multithreaded Applications.pdf b/docs/prj/resources/Hoard - A Scalable Memory Allocator for Multithreaded Applications.pdf new file mode 100644 index 0000000..6fe5cd1 Binary files /dev/null and b/docs/prj/resources/Hoard - A Scalable Memory Allocator for Multithreaded Applications.pdf differ diff --git a/docs/prj/resources/Magazines and Vmem - Extending the Slab Allocator to Many CPUs and Arbitrary Resources.pdf b/docs/prj/resources/Magazines and Vmem - Extending the Slab Allocator to Many CPUs and Arbitrary Resources.pdf new file mode 100644 index 0000000..1b1b73a Binary files /dev/null and b/docs/prj/resources/Magazines and Vmem - Extending the Slab Allocator to Many CPUs and Arbitrary Resources.pdf differ diff --git a/docs/prj/resources/The Slab Allocator - An Object-Caching Kernel Memory Allocator.pdf b/docs/prj/resources/The Slab Allocator - An Object-Caching Kernel Memory Allocator.pdf new file mode 100644 index 0000000..7b0bbd3 Binary files /dev/null and b/docs/prj/resources/The Slab Allocator - An Object-Caching Kernel Memory Allocator.pdf differ diff --git a/include/chevron/common/macro_defs.h b/include/chevron/common/macro_defs.h new file mode 100644 index 0000000..084b804 --- /dev/null +++ b/include/chevron/common/macro_defs.h @@ -0,0 +1,98 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file macro_defs.h + * + * @brief + * Defines library-wide macro definitions. + * + * @author + * Jamon T. Bailey + * + * @date 04-22-2026 + */ + +#ifndef CHEVRON_LIB_HDR_COMMON_MACRO_DEFINITIONS_H_ +#define CHEVRON_LIB_HDR_COMMON_MACRO_DEFINITIONS_H_ + +// ===================================================================================== // +// [ ARCHITECTURE DETECTION ] +// +// Identifies the CPU architecture of the target platform. Each supported architecture +// is probed with both its GCC/Clang spelling and its MSVC spelling, since the two +// compiler families do not share a common macro for this. +// ===================================================================================== // + +#if defined(__x86_64__) || defined(_M_X64) + #define CHEVRON_ARCH_X86_64 1 +#elif defined(__i386__) || defined(_M_IX86) + #define CHEVRON_ARCH_X86 1 +#elif defined(__aarch64__) || defined(_M_ARM64) + #define CHEVRON_ARCH_ARM64 1 +#elif defined(__arm__) || defined(_M_ARM) + #define CHEVRON_ARCH_ARM 1 +#endif + +// ===================================================================================== // +// [ COMPILER DETECTION ] +// +// Identifies the compiler building Chevron. Clang is checked before GCC because Clang +// defines `__GNUC__` for GCC compatibility, and MSVC is identified through `_MSC_VER`. +// ===================================================================================== // + +#if defined(__clang__) + #define CHEVRON_CLANG 1 +#elif defined(__GNUC__) + #define CHEVRON_GCC 1 +#elif defined(_MSC_VER) + #define CHEVRON_MSVC 1 +#else + #error "Chevron does not support this compiler." +#endif + +// ===================================================================================== // +// [ OPERATING SYSTEM DETECTION ] +// +// Identifies the operating system of the target platform. `_WIN32` is defined on both +// 32 and 64-bit Windows and is the canonical Windows marker; `_WIN64` is checked +// alongside it defensively. Cygwin is treated as a distinct branch because it targets +// a POSIX layer on top of Windows rather than the native Win32 API. +// ===================================================================================== // + +#if defined(_WIN32) || defined(_WIN64) + #define CHEVRON_WINDOWS 1 +#elif defined(__CYGWIN__) + #define CHEVRON_CYGWIN 1 +#elif defined(__APPLE__) + #define CHEVRON_MACOS 1 +#elif defined(__linux__) + #define CHEVRON_LINUX 1 +#else + #error "Chevron does not support this operating system." +#endif + +// ===================================================================================== // +// [ POINTER-WIDTH DETECTION ] +// +// Identifies the target platforms pointer/address width using `UINTPTR_MAX` defined in +// ``, which represents the maximum value of `uintptr_t`. This approach evades +// the complexities of vendor-specific macros. +// ===================================================================================== // + +#include + +#if UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu + #define CHEVRON_64BIT 1 + #define CHEVRON_PTR_WIDTH 64 +#elif UINTPTR_MAX == 0xFFFFFFFFu + #define CHEVRON_32BIT 1 + #define CHEVRON_PTR_WIDTH 32 +#else + #error "Chevron only supports 32/64-bit platforms." +#endif + +#endif // CHEVRON_LIB_HDR_COMMON_MACRO_DEFINITIONS_H_ diff --git a/include/chevron/common/units/digital/digital_size.hpp b/include/chevron/common/units/digital/digital_size.hpp new file mode 100644 index 0000000..bb9a855 --- /dev/null +++ b/include/chevron/common/units/digital/digital_size.hpp @@ -0,0 +1,605 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file digital_size.hpp + * + * @brief + * Digital size quantity template. + * + * @author + * Jamon T. Bailey + * + * @date 04-17-2026 + */ + +#ifndef CHEVRON_LIB_HDR_DIGITAL_SIZE_TEMPLATE_H_ +#define CHEVRON_LIB_HDR_DIGITAL_SIZE_TEMPLATE_H_ + +#include +#include +#include +#include +#include +#include "chevron/common/units/digital/unit_cast.hpp" +#include "chevron/common/units/digital/size_concepts.hpp" + +namespace chevron::units +{ + +/*! + * @brief + * Binary-based digital size unit magnitude. + */ +inline constexpr uint64_t BINARY_DIGITAL_UNIT_MAGNITUDE = 1024; + +/*! + * @brief + * Decimal-based digital size unit magnitude. + */ +inline constexpr uint64_t DECIMAL_DIGITAL_UNIT_MAGNITUDE = 1000; + +/*! + * @brief + * Byte-based digital size quantity template. + * + * @details + * N/a + */ +template +class DigitalSize { + // ===================================================================================== // + // <> chevron::units::DigitalSize | [PRIVATE] NESTED TYPES + // ===================================================================================== // + + /*! @brief Highest digital size resolution (Bytes). */ + using ByteResolution = DigitalSize<1ULL>; + + // ===================================================================================== // + // <> chevron::units::DigitalSize | [PUBLIC] NESTED TYPES + // ===================================================================================== // +public: + /*! @brief Alias of underlying byte representation. */ + using ReprType = uint64_t; + /*! @brief Ratio detailing total bytes in this unit. */ + using ByteRatio = std::ratio; + + // ===================================================================================== // + // <> chevron::units::DigitalSize | CONSTRUCTORS / DESTRUCTOR + // ===================================================================================== // + + /*! @brief Default construct with a digital size of 0 bytes. */ + constexpr DigitalSize() noexcept = default; + + /*! + * @brief + * Construct digital size quantity with specified unit count. + */ + constexpr explicit DigitalSize(ReprType units) noexcept + : unitCount_{units} + { + // + } + + /*! + * @brief + * Construct digital size quantity with different size units + * (lossy). + */ + template + constexpr explicit DigitalSize(const DigitalSize& other) + : unitCount_{DigitalSizeCast>::cast(other).count()} + { + // + } + + /*! + * @brief + * Construct digital size quantity with different size units + * (lossless). + */ + template + constexpr DigitalSize(const DigitalSize& other) + requires concepts::lossless_digital_size_conversion, DigitalSize> + : unitCount_{DigitalSizeCast>::cast(other).count()} + { + // + } + + ~DigitalSize() noexcept = default; + + // ===================================================================================== // + // <> chevron::units::DigitalSize | [PUBLIC] MEMBER METHODS + // ===================================================================================== // + + /*! + * @brief + * Returns raw count of digital units. + * + * @return + * Raw count of digital units + */ + constexpr ReprType count() const noexcept + { + return unitCount_; + } + + /*! + * @brief + * Returns total number of bytes in this size. + * + * @return + * This size in bytes + */ + constexpr ReprType bytes() const noexcept + { + return unitCount_ * ByteRatio::num / ByteRatio::den; + } + + /*! + * @brief + * Returns total number of bytes in this size as size_t. + * + * @return + * This size in bytes + */ + constexpr size_t size_t_bytes() const noexcept(sizeof(size_t) >= sizeof(ReprType)) + { + const ReprType byteCount = bytes(); + + if constexpr (sizeof(size_t) < sizeof(ReprType)) { + if (byteCount > std::numeric_limits::max()) { + throw std::overflow_error( + "DigitalSize::size_t_bytes(): Byte count exceeds size_t capacity" + ); + } + } + + return static_cast(byteCount); + } + + /*! + * @brief + * Calculates absolute difference between this and + * another digital size. + * + * @details + * The difference operation conducted in this method + * is direction independent. It returns the positive + * difference between the two regardless of which is + * larger. This is meaningful when the question is + * "how far apart are two digital sizes?". + * + * @return + * Absolute difference between DigitalSize values + */ + template + constexpr auto absoluteDifference(const DigitalSize& other) const noexcept + { + using Self = DigitalSize; + using Other = DigitalSize; + using FinerUnit = traits::finer_size_t; + + const ReprType selfUnits = DigitalSizeCast::cast(*this).count(); + const ReprType otherUnits = DigitalSizeCast::cast(other).count(); + return FinerUnit{ + std::max(selfUnits, otherUnits) - std::min(selfUnits, otherUnits) + }; + } + + // ===================================================================================== // + // <> chevron::units::DigitalSize | OPERATORS + // ===================================================================================== // + + /*! + * @brief + * Tests whether this and another digital size represent + * the same byte count. + * + * @details + * The comparison is performed in bytes, so values from + * different units compare as equal when they represent + * the same size (i.e. `1_MiB == 1024_KiB` is a true + * statement). + * + * @return + * True if equivalent sizes + */ + template + constexpr bool operator==(const DigitalSize& other) const noexcept + { + return this->bytes() == other.bytes(); + } + + /*! + * @brief + * Tests whether this digital size is strictly less than + * another. + * + * @return + * True if left-hand side is smaller + */ + template + constexpr bool operator<(const DigitalSize& other) const noexcept + { + return this->bytes() < other.bytes(); + } + + /*! + * @brief + * Tests whether this digital size is strictly greater + * than another. + * + * @return + * True if left-hand side is greater + */ + template + constexpr bool operator>(const DigitalSize& other) const noexcept + { + return this->bytes() > other.bytes(); + } + + /*! + * @brief + * Adds another digital size of any unit to this one. + * + * @details + * Same-system arithmetic returns the finer unit of + * the two types. Cross-system arithmetic returns + * `Bytes` since this is the only unit the binary + * and decimal size systems can represent exact. + * Addition conducted through this operator is + * always lossless. + * + * @return + * Sum of two digital sizes in the greatest common unit + */ + template + constexpr auto operator+(const DigitalSize& other) const noexcept + { + using Self = DigitalSize; + using Other = DigitalSize; + + if constexpr (concepts::matching_digital_size_systems) { + using FinerUnit = traits::finer_size_t; + + const FinerUnit lhs = DigitalSizeCast::cast(*this); + const FinerUnit rhs = DigitalSizeCast::cast(other); + return FinerUnit{ lhs.count() + rhs.count() }; + } + else { + return ByteResolution{ this->bytes() + other.bytes() }; + } + } + + /*! + * @brief + * Subtracts another digital size of any unit from + * this one. + * + * @details + * Same-system arithmetic returns the finer unit of + * the two types. Cross-system arithmetic returns + * `Bytes` since this is the only unit the binary + * and decimal size systems can represent exact. + * Subtraction conducted through this operator is + * always lossless. + * + * @return + * Difference of two digital sizes in the greatest + * common unit + */ + template + constexpr auto operator-(const DigitalSize& other) const noexcept + { + using Self = DigitalSize; + using Other = DigitalSize; + + if constexpr (concepts::matching_digital_size_systems) { + using FinerUnit = traits::finer_size_t; + + const FinerUnit lhs = DigitalSizeCast::cast(*this); + const FinerUnit rhs = DigitalSizeCast::cast(other); + return FinerUnit{ lhs.count() - rhs.count() }; + } + else { + return ByteResolution{ this->bytes() - other.bytes() }; + } + } + + /*! + * @brief + * Calculates remainder of dividing this digital size + * by another. + * + * @details + * Same-system arithmetic returns the finer unit of + * the two types. Cross-system arithmetic returns + * `Bytes` since this is the only unit the binary + * and decimal size systems can represent exact. + * Modulo conducted through this operator is always + * lossless. + * + * @return + * Remainder of division between digital sizes + */ + template + constexpr auto operator%(const DigitalSize& other) const + { + using Self = DigitalSize; + using Other = DigitalSize; + + if constexpr (concepts::matching_digital_size_systems) { + using FinerUnit = traits::finer_size_t; + + const FinerUnit lhs = DigitalSizeCast::cast(*this); + const FinerUnit rhs = DigitalSizeCast::cast(other); + + if (rhs.count() == 0) + throw std::invalid_argument{"DigitalSize::operator%(): Division by zero."}; + + return FinerUnit{ lhs.count() % rhs.count() }; + } + else { + if (other.bytes() == 0) + throw std::invalid_argument{"DigitalSize::operator%(): Division by zero."}; + + return ByteResolution{ this->bytes() % other.bytes() }; + } + } + + /*! + * @brief + * Multiplies this digital size by a scalar. + * + * @note + * The unit type is always preserved during this + * operation; only the unit count is scaled. + * + * @return + * Scaled digital size in same units + */ + constexpr DigitalSize operator*(const ReprType scalar) const noexcept + { + return DigitalSize{this->unitCount_ * scalar}; + } + + /*! + * @brief + * Divides this digital size by a scalar. + * + * @note + * The unit type is always preserved during this + * operation; only the unit count is scaled. + * + * @return + * Scaled digital size in same units + */ + constexpr DigitalSize operator/(const ReprType scalar) const + { + if (scalar == 0) + throw std::invalid_argument{"DigitalSize::operator/(): Division by zero."}; + + return DigitalSize{this->unitCount_ / scalar}; + } + + /*! + * @brief + * Divides this digital size by another. + * + * @details + * Both operands are converted to bytes before division. + * The result is a `double` to preserve precision in the + * resulting quotient. + * + * @return + * Quotient of two digital sizes as a double + */ + template + constexpr double operator/(const DigitalSize& other) const + { + if (other.count() == 0) + throw std::invalid_argument{"DigitalSize::operator/(): Division by zero."}; + + return static_cast(this->bytes()) / static_cast(other.bytes()); + } + + /*! + * @brief + * Assigns another digital size to this. + * + * @details + * This operator is only applicable to lossless + * assignment operations. + */ + template + DigitalSize& operator=(const DigitalSize& other) noexcept + requires concepts::lossless_digital_size_conversion, DigitalSize> + { + using Self = DigitalSize; + + this->unitCount_ = DigitalSizeCast::cast(other).count(); + return *this; + } + + // ===================================================================================== // + // <> chevron::units::DigitalSize | COMPOUND OPERATORS + // ===================================================================================== // + + /*! + * @brief + * Tests whether this digital size is less than or equal + * to another. + * + * @return + * True if left-hand side is smaller or equal + */ + template + constexpr bool operator<=(const DigitalSize& other) const noexcept + { + return this->bytes() <= other.bytes(); + } + + /*! + * @brief + * Tests whether this digital size is greater than or + * equal to another. + * + * @return + * True if left-hand side is greater or equal + */ + template + constexpr bool operator>=(const DigitalSize& other) const noexcept + { + return this->bytes() >= other.bytes(); + } + + /*! + * @brief + * In-place addition. + * + * @details + * The right-hand side is constrained to the resolution + * of the left-hand side units during an in-place + * addition operation. + * + * @note + * The unit type is always preserved during in-place + * operations. + */ + template + DigitalSize& operator+=(const DigitalSize& other) noexcept + { + using Self = DigitalSize; + + this->unitCount_ += DigitalSizeCast::cast(other).count(); + return *this; + } + + /*! + * @brief + * In-place subtraction. + * + * @details + * The right-hand side is constrained to the resolution + * of the left-hand side units during an in-place + * subtraction operation. + * + * @note + * The unit type is always preserved during in-place + * operations. + */ + template + DigitalSize& operator-=(const DigitalSize& other) noexcept + { + using Self = DigitalSize; + + this->unitCount_ -= DigitalSizeCast::cast(other).count(); + return *this; + } + + /*! + * @brief + * In-place modulus division. + * + * @details + * This operator is only available when the right-hand + * side is losslessly convertible to this types units. + * Combinations that would truncate the divisor are + * rejected from using this signature. In those cases + * the caller must use `operator%()` and store that + * result in another variable. In-place operators are + * intentionally designed to preserve this types units. + * + * @note + * The unit type is always preserved during in-place + * operations. + */ + template + DigitalSize& operator%=(const DigitalSize& other) + requires concepts::lossless_digital_size_conversion, DigitalSize> + { + using Self = DigitalSize; + + const ReprType otherUnitCount = DigitalSizeCast::cast(other).count(); + + if (otherUnitCount == 0) + throw std::invalid_argument{"DigitalSize::operator%=(): Division by zero."}; + + this->unitCount_ %= otherUnitCount; + return *this; + } + + /*! + * @brief + * In-place scalar multiplication. + * + * @note + * The unit type is always preserved during in-place + * operations. + */ + DigitalSize& operator*=(const ReprType scalar) noexcept + { + this->unitCount_ *= scalar; + return *this; + } + + /*! + * @brief + * In-place scalar division. + * + * @note + * The unit type is always preserved during in-place + * operations. + */ + DigitalSize& operator/=(const ReprType scalar) + { + if (scalar == 0) + throw std::invalid_argument{"DigitalSize::operator/=(): Division by zero."}; + + this->unitCount_ /= scalar; + return *this; + } + + // ===================================================================================== // + // <> chevron::units::DigitalSize | [PRIVATE] ATTRIBUTES + // ===================================================================================== // +private: + ReprType unitCount_; +}; + +namespace traits { + +/* ------------------------------------------------------------------------------------- */ +// > is_digital_size | TYPE TRAIT +/* ------------------------------------------------------------------------------------- */ + +/*! + * @brief + * Base specialization of `DigitalSize` type validation. + */ +template +struct is_digital_size : std::false_type {}; + +/*! + * @brief + * Specialization for any `DigitalSize` instantiation. + */ +template +struct is_digital_size> : std::true_type {}; + +/*! + * @brief + * Convenience alias for `DigitalSize` type validation. + */ +template +constexpr bool is_digital_size_v = is_digital_size::value; + +} + +} + +#endif // CHEVRON_LIB_HDR_DIGITAL_SIZE_TEMPLATE_H_ diff --git a/include/chevron/common/units/digital/size_concepts.hpp b/include/chevron/common/units/digital/size_concepts.hpp new file mode 100644 index 0000000..2ed2114 --- /dev/null +++ b/include/chevron/common/units/digital/size_concepts.hpp @@ -0,0 +1,148 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file size_concepts.hpp + * + * @brief + * Defines digital unit entity related type concepts. + * + * @author + * Jamon T. Bailey + * + * @date 04-20-2026 + */ + +#ifndef CHEVRON_LIB_HDR_DIGITAL_UNIT_TYPE_CONCEPTS_H_ +#define CHEVRON_LIB_HDR_DIGITAL_UNIT_TYPE_CONCEPTS_H_ + +#include +#include "chevron/common/units/digital/type_traits.hpp" + +namespace chevron::units::concepts +{ + +/*! + * @brief + * Validates `Units` exposes a nested ByteRatio type that + * is a `std::ratio`. + */ +template +concept has_byte_ratio_specification = requires { + requires traits::is_std_ratio_v; +}; + +/*! + * @brief + * Validates conversion between provided units is lossless. + */ +template +concept lossless_digital_size_conversion = requires { + requires has_byte_ratio_specification + && has_byte_ratio_specification; + requires traits::is_lossless_ratio_conversion_v< + typename From_Units::ByteRatio, typename To_Units::ByteRatio>; +}; + +/*! + * @brief + * Validates `UnitsT` belongs to the IEC binary digital size + * system. + */ +template +concept binary_digital_size_units = requires { + requires has_byte_ratio_specification; + requires traits::is_binary_size_system_v; +}; + +/*! + * @brief + * Validates `UnitsT` belongs to the SI decimal digital size + * system. + */ +template +concept decimal_digital_size_units = requires { + requires has_byte_ratio_specification; + requires traits::is_decimal_size_system_v; +}; + +/*! + * @brief + * Validates `Units_A` and `Units_B` belong to the same digital + * size system. + * + * @note + * This concept does **NOT** check whether the two units are equal. + * It asks whether they share the same baseline unit magnitude. The + * IEC binary size system is based on 1,024; the SI decimal size + * system is based on 1,000. + */ +template +concept matching_digital_size_systems = requires { + requires (traits::is_binary_size_system_v && traits::is_binary_size_system_v) + || (traits::is_decimal_size_system_v && traits::is_decimal_size_system_v); +}; + +/*! + * @brief + * Validates `UnitsT` exposes the `DigitalSize` accessor API. + */ +template +concept digital_size_unit_api = requires(const UnitsT& u) { + { u.count() } -> std::same_as; + { u.bytes() } -> std::same_as; + { u.size_t_bytes() } -> std::same_as; +}; + +/*! + * @brief + * Validates `UnitsT` exposes the `DigitalSize` arithmetic + * operations API. + */ +template +concept digital_size_unit_arithmetic = requires(UnitsT& u, typename UnitsT::ReprType i) { + // Relational operators + { u < u } -> std::same_as; + { u > u } -> std::same_as; + { u == u } -> std::same_as; + { u <= u } -> std::same_as; + { u >= u } -> std::same_as; + // NOTE: Heterogeneous relational operations not covered by the above + + // Arithmetic operators + { u + u } -> std::same_as; + { u - u } -> std::same_as; + { u % u } -> std::same_as; + { u / u } -> std::same_as; + // NOTE: Heterogeneous arithmetic operations not covered by the above + { u * i } -> std::same_as; + { u / i } -> std::same_as; + + // Arithmetic assignment operators + { u += u } -> std::same_as; + { u -= u } -> std::same_as; + { u %= u } -> std::same_as; + // NOTE: Heterogeneous assignment operations not covered by the above + { u *= i } -> std::same_as; + { u /= i } -> std::same_as; +}; + +/*! + * @brief + * Validates `UnitsT` participates in the `DigitalSize` + * unit system. + */ +template +concept digital_size_units = requires { + requires std::unsigned_integral; + requires digital_size_unit_api; + requires digital_size_unit_arithmetic; + requires binary_digital_size_units || decimal_digital_size_units; +}; + +} + +#endif // CHEVRON_LIB_HDR_DIGITAL_UNIT_TYPE_CONCEPTS_H_ diff --git a/include/chevron/common/units/digital/size_units.hpp b/include/chevron/common/units/digital/size_units.hpp new file mode 100644 index 0000000..bfd84e9 --- /dev/null +++ b/include/chevron/common/units/digital/size_units.hpp @@ -0,0 +1,112 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file size_units.hpp + * + * @brief + * Digital size unit type aliases. + * + * @author + * Jamon T. Bailey + * + * @date 04-19-2026 + */ + +#ifndef CHEVRON_LIB_HDR_DIGITAL_SIZE_UNIT_ALIASES_H_ +#define CHEVRON_LIB_HDR_DIGITAL_SIZE_UNIT_ALIASES_H_ + +#include "chevron/common/units/digital/digital_size.hpp" +#include "chevron/utility/math/algebra.hpp" + +namespace chevron::units +{ + +// ===================================================================================== // +// <> chevron::units::DigitalSize | TYPE ALIASES +// ===================================================================================== // + +/*! + * @brief + * Bytes. + */ +using Bytes = units::DigitalSize<1>; + +/* ------------------------------------------------------------------------------------- */ +// > Decimal Digital Size Units +/* ------------------------------------------------------------------------------------- */ + +/*! + * @brief + * Kilobyte. + */ +using KB = units::DigitalSize; + +/*! + * @brief + * Megabyte. + */ +using MB = units::DigitalSize; + +/*! + * @brief + * Gigabyte. + */ +using GB = units::DigitalSize; + +/*! + * @brief + * Terabyte. + */ +using TB = units::DigitalSize; + +/* ------------------------------------------------------------------------------------- */ +// > Binary Digital Size Units +/* ------------------------------------------------------------------------------------- */ + +/*! + * @brief + * Kilobyte (IEC Standard - Kibibyte). + * + * @note + * This is a binary-based digital size unit that should not be + * confused with its decimal counterpart. + */ +using KiB = units::DigitalSize; + +/*! + * @brief + * Megabyte (IEC Standard - Mebibyte). + * + * @note + * This is a binary-based digital size unit that should not be + * confused with its decimal counterpart. + */ +using MiB = units::DigitalSize; + +/*! + * @brief + * Gigabyte (IEC Standard - Gibibyte). + * + * @note + * This is a binary-based digital size unit that should not be + * confused with its decimal counterpart. + */ +using GiB = units::DigitalSize; + +/*! + * @brief + * Terabyte (IEC Standard - Tebibyte). + * + * @note + * This is a binary-based digital size unit that should not be + * confused with its decimal counterpart. + */ +using TiB = units::DigitalSize; + +} + +#endif // CHEVRON_LIB_HDR_DIGITAL_SIZE_UNIT_ALIASES_H_ diff --git a/include/chevron/common/units/digital/type_traits.hpp b/include/chevron/common/units/digital/type_traits.hpp new file mode 100644 index 0000000..d111385 --- /dev/null +++ b/include/chevron/common/units/digital/type_traits.hpp @@ -0,0 +1,145 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file type_traits.hpp + * + * @brief + * Defines digital unit entity related type traits. + * + * @author + * Jamon T. Bailey + * + * @date 04-17-2026 + */ + +#ifndef CHEVRON_LIB_HDR_DIGITAL_UNIT_TYPE_TRAITS_H_ +#define CHEVRON_LIB_HDR_DIGITAL_UNIT_TYPE_TRAITS_H_ + +#include +#include +#include "chevron/utility/bits/powers.hpp" + +namespace chevron::units::traits +{ + +/* ------------------------------------------------------------------------------------- */ +// > is_std_ratio | TYPE TRAIT +/* ------------------------------------------------------------------------------------- */ + +/*! + * @brief + * Base specialization of STL `std::ratio` type validation. + */ +template +struct is_std_ratio : std::false_type {}; + +/*! + * @brief + * Specialization for any STL `std::ratio` instantiation. + */ +template +struct is_std_ratio> : std::true_type {}; + +/*! + * @brief + * Convenience alias for STL `std::ratio` type validation. + */ +template +constexpr bool is_std_ratio_v = is_std_ratio::value; + +/* ------------------------------------------------------------------------------------- */ +// > finer_ratio / coarser_ratio | TYPE TRAIT +/* ------------------------------------------------------------------------------------- */ + +/*! + * @brief + * Determine which of two ratios is smaller. + */ +template +using finer_ratio_t = std::conditional_t< + std::ratio_less_v, Ratio_A, Ratio_B>; + +/*! + * @brief + * Determine which of two ratios is larger. + */ +template +using coarser_ratio_t = std::conditional_t< + !std::ratio_less_v, Ratio_A, Ratio_B>; + +/* ------------------------------------------------------------------------------------- */ +// > is_lossless_ratio_conversion | TYPE TRAIT +/* ------------------------------------------------------------------------------------- */ + +/*! + * @brief + * Validates conversion between provided ratios is lossless. + * + * @details + * A conversion is lossless when the source ratio is a + * whole-number multiple of the target ratio. This is verified + * by dividing the two ratios and confirming the denominator + * of the **reduced** result is 1. + */ +template +constexpr bool is_lossless_ratio_conversion_v = std::ratio_divide::den == 1; + +/* ------------------------------------------------------------------------------------- */ +// > finer_size / coarser_size | TYPE TRAIT +/* ------------------------------------------------------------------------------------- */ + +/*! + * @brief + * Determine which of two digital size units is smaller. + */ +template +using finer_size_t = std::conditional_t< + std::ratio_less_v, Units_A, Units_B>; + +/*! + * @brief + * Determine which of two digital size units is larger. + */ +template +using coarser_size_t = std::conditional_t< + !std::ratio_less_v, Units_A, Units_B>; + +/* ------------------------------------------------------------------------------------- */ +// > is_binary_size_system / is_decimal_size_system | TYPE TRAIT +/* ------------------------------------------------------------------------------------- */ + +/*! + * @brief + * Validates that `UnitsT` belongs to the IEC binary digital + * size system. + */ +template +constexpr bool is_binary_size_system_v = + requires { typename UnitsT::ByteRatio; } + && requires { typename UnitsT::ReprType; } + && (UnitsT::ByteRatio::den == 1) + && bits::isPowerOfTwo( + static_cast(UnitsT::ByteRatio::num) + ); + +/*! + * @brief + * Validates that `UnitsT` belongs to the SI decimal digital + * size system. + */ +template +constexpr bool is_decimal_size_system_v = + requires { typename UnitsT::ByteRatio; } + && requires { typename UnitsT::ReprType; } + && (UnitsT::ByteRatio::den == 1) + && bits::isPowerOfTen( + static_cast(UnitsT::ByteRatio::num) + ); + +} + +#endif // CHEVRON_LIB_HDR_DIGITAL_UNIT_TYPE_TRAITS_H_ diff --git a/include/chevron/common/units/digital/unit_cast.hpp b/include/chevron/common/units/digital/unit_cast.hpp new file mode 100644 index 0000000..3f9ac06 --- /dev/null +++ b/include/chevron/common/units/digital/unit_cast.hpp @@ -0,0 +1,92 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file unit_cast.hpp + * + * @brief + * Digital size quantity cast utility. + * + * @author + * Jamon T. Bailey + * + * @date 04-18-2026 + */ + +#ifndef CHEVRON_LIB_HDR_DIGITAL_SIZE_UNIT_CAST_H_ +#define CHEVRON_LIB_HDR_DIGITAL_SIZE_UNIT_CAST_H_ + +#include +#include +#include "chevron/common/units/digital/size_concepts.hpp" + +namespace chevron::units +{ + +/*! + * @brief + * Performs unconditional conversions between digital size units. + * + * @important + * Conversions that go from finer to coarser grained units can + * experience truncation (information loss) if the finer unit is + * not in multiples of the coarser unit (i.e. 1,024 Bytes -> KB + * = 1 KB with 24 bytes discarded). Conversions are determined to + * be lossy or lossless at the call site. + * + * @details + * Given a digital size quantity expressed in one unit, an equivalent + * quantity is provided in another specified digital size unit. The + * target units are specified explicitly and the source units are + * deduced from the `cast()` argument. + * + * The cast is unconditional regardless of the possibility of lossing + * information in the process. Conversions that cannot be represented + * exact in the target units are truncated toward zero. Callers of this + * utility are expected to be aware of lossy conversions during cast + * that go from finer units to coarser units. + * + * Truncation also occurs when casting between binary and decimal based + * digital size systems (i.e. casting 1 KiB to 1 KB). The two sizing + * systems work with different unit magnitude baselines (KiB = 1024 + * bytes vs. KB = 1000 bytes). The additional 24 bytes present in the + * binary KiB are effectively discarded in the process rendering the + * operation lossy. In the reverse direction, 1 KB is truncated to + * 0 KiB since the decimal magnitude baseline is short 24 bytes to a + * full 1 KiB. + */ +template +struct DigitalSizeCast { + /*! + * @brief + * Converts source units to an equivalent value in target + * units. + * + * @return + * Converted digital size units + */ + template + static constexpr To_Units cast(const From_Units units) noexcept + { + using SourceRatio = typename From_Units::ByteRatio; + using TargetRatio = typename To_Units::ByteRatio; + using Factor = std::ratio_divide; + + return To_Units{ (units.count() * Factor::num) / Factor::den }; + } + + DigitalSizeCast() noexcept = delete; + ~DigitalSizeCast() noexcept = delete; +}; + +// TODO: Template should be `template ` +// but integrating the concept appears to cause issues with casting +// operations. This same concept should also be applied to the deduced +// type in the `cast()` template method. + +} + +#endif // CHEVRON_LIB_HDR_DIGITAL_SIZE_UNIT_CAST_H_ diff --git a/include/chevron/function.hpp b/include/chevron/function.hpp index 85ae862..393c826 100644 --- a/include/chevron/function.hpp +++ b/include/chevron/function.hpp @@ -16,7 +16,6 @@ #include "chevron/utility/function/func_args.hpp" #include "chevron/utility/function/callable.hpp" -#include namespace chevron { @@ -24,29 +23,58 @@ namespace chevron /*! @brief Callable function that accepts no arguments and returns void. */ using VoidReturnNoArgs = Callable; +/*! @brief Callable function that accepts specified arguments and returns void. */ +template +using VoidReturnArgs = Callable>; + /*! @brief Callable function that accepts no arguments and returns a boolean. */ using BoolReturnNoArgs = Callable; +/*! @brief Callable function that accepts specified arguments and returns a boolean. */ +template +using BoolReturnArgs = Callable>; + /*! @brief Callable function that accepts no arguments and returns a character. */ using CharReturnNoArgs = Callable; +/*! @brief Callable function that accepts specified arguments and returns a character. */ +template +using CharReturnArgs = Callable>; + /*! @brief Callable function that accepts no arguments and returns an integer. */ using IntReturnNoArgs = Callable; +/*! @brief Callable function that accepts specified arguments and returns an integer. */ +template +using IntReturnArgs = Callable>; + /*! @brief Callable function that accepts no arguments and returns a float. */ using FloatReturnNoArgs = Callable; +/*! @brief Callable function that accepts specified arguments and returns a float. */ +template +using FloatReturnArgs = Callable>; + /*! @brief Callable function that accepts no arguments and returns a double. */ using DoubleReturnNoArgs = Callable; +/*! @brief Callable function that accepts specified arguments and returns a double. */ +template +using DoubleReturnArgs = Callable>; + /*! @brief Callable function that accepts no arguments and returns a const char pointer. */ using CstrReturnNoArgs = Callable; -/*! @brief Callable function that accepts no arguments and returns a string. */ -using StringReturnNoArgs = Callable; +/*! @brief Callable function that accepts specified arguments and returns a const char pointer. */ +template +using CstrReturnArgs = Callable>; /*! @brief Callable function that accepts no arguments and returns size_t. */ -using SizeReturnNoArgs = Callable; +using SizeTReturnNoArgs = Callable; + +/*! @brief Callable function that accepts specified arguments and returns size_t. */ +template +using SizeTReturnArgs = Callable>; /*! @brief Callable function that accepts no arguments and returns specified type. */ template diff --git a/include/chevron/process/memory/mem_pool_config.hpp b/include/chevron/process/memory/mem_pool_config.hpp new file mode 100644 index 0000000..12dffa5 --- /dev/null +++ b/include/chevron/process/memory/mem_pool_config.hpp @@ -0,0 +1,68 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file mem_pool_config.hpp + * + * @brief + * Declaration of process-wide block pool configuration. + * + * @author + * Jamon T. Bailey + * + * @date 04-14-2026 + */ + +#ifndef CHEVRON_LIB_PROCESS_MEMORY_POOL_CONFIGURATION_H_ +#define CHEVRON_LIB_PROCESS_MEMORY_POOL_CONFIGURATION_H_ + +#include "chevron/units.hpp" +#include "chevron/common/export.h" + +namespace chevron::process +{ + +/*! + * @brief + * Process-wide memory block pool configuration. + * + * @details + * N/a + */ +struct CHEVRON_API MemoryPoolConfig { + Bytes block_size; + Bytes chunk_size; + size_t block_alignment; + Bytes budget_ceiling; + size_t initial_thread_blocks; + size_t max_thread_blocks; + + /*! + * @brief + * TODO: INCOMPLETE DOCUMENTATION!!! + * + * @return + * True if valid memory configuration + */ + [[nodiscard]] bool isValid() const noexcept; + + /*! + * @brief + * TODO: INCOMPLETE DOCUMENTATION!!! + */ + void isValidOrThrow() const; + +private: + /*! + * @brief + * TODO: INCOMPLETE DOCUMENTATION!!! + */ + [[nodiscard]] bool validate(const char** reason) const noexcept; +}; + +} + +#endif // CHEVRON_LIB_PROCESS_MEMORY_POOL_CONFIGURATION_H_ diff --git a/include/chevron/process/memory/memory_core.hpp b/include/chevron/process/memory/memory_core.hpp new file mode 100644 index 0000000..f3dfa56 --- /dev/null +++ b/include/chevron/process/memory/memory_core.hpp @@ -0,0 +1,38 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file memory_core.hpp + * + * @brief + * // TODO: INCOMPLETE DOC STRING!!! + * + * @author + * Jamon T. Bailey + * + * @date 04-01-2026 + */ + +#ifndef CHEVRON_LIB_PROCESS_MEMORY_AUTHORITY_H_ +#define CHEVRON_LIB_PROCESS_MEMORY_AUTHORITY_H_ + +#include "chevron/process/memory/proc_mem_pool.hpp" + +namespace chevron::process +{ + +/*! + * @brief + * Process memory authority. + * + * @details + * N/a + */ +class MemoryCore { /* TODO : INCOMPLETE IMPLEMENTATION!!! */ }; + +} + +#endif // CHEVRON_LIB_PROCESS_MEMORY_AUTHORITY_H_ diff --git a/include/chevron/process/memory/proc_mem_pool.hpp b/include/chevron/process/memory/proc_mem_pool.hpp new file mode 100644 index 0000000..b09c14e --- /dev/null +++ b/include/chevron/process/memory/proc_mem_pool.hpp @@ -0,0 +1,38 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file proc_mem_pool.hpp + * + * @brief + * Declaration of process-wide fixed-size memory block pool. + * + * @author + * Jamon T. Bailey + * + * @date 04-14-2026 + */ + +#ifndef CHEVRON_LIB_PROCESS_MEMORY_POOL_H_ +#define CHEVRON_LIB_PROCESS_MEMORY_POOL_H_ + +#include "chevron/process/memory/mem_pool_config.hpp" + +namespace chevron::process +{ + +/*! + * @brief + * Process-wide fixed-size memory block pool. + * + * @details + * N/a + */ +class ProcessMemoryPool { /* TODO : INCOMPLETE IMPLEMENTATION!!! */ }; + +} + +#endif // CHEVRON_LIB_PROCESS_MEMORY_POOL_H_ diff --git a/include/chevron/units.hpp b/include/chevron/units.hpp new file mode 100644 index 0000000..80aa701 --- /dev/null +++ b/include/chevron/units.hpp @@ -0,0 +1,177 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file units.hpp + * + * @brief + * General include header for unit measure related facilities. + * + * @author + * Jamon T. Bailey + * + * @date 04-18-2026 + */ + +#ifndef CHEVRON_LIB_HDR_EXPLICIT_UNITS_INCLUDE_H_ +#define CHEVRON_LIB_HDR_EXPLICIT_UNITS_INCLUDE_H_ + +#include "chevron/common/units/digital/digital_size.hpp" +#include "chevron/common/units/digital/size_units.hpp" +#include "chevron/common/units/digital/unit_cast.hpp" + +namespace chevron +{ + +// ===================================================================================== // +// <> DigitalSize | TYPE ALIASES +// ===================================================================================== // + +using units::Bytes; ///< Byte + +/* ------------------------------------------------------------------------------------- */ +// > Binary Digital Size Units (IEC) +/* ------------------------------------------------------------------------------------- */ + +using units::KiB; ///< Kibibyte +using units::MiB; ///< Mebibyte +using units::GiB; ///< Gibibyte +using units::TiB; ///< Tebibyte + +/* ------------------------------------------------------------------------------------- */ +// > Decimal Digital Size Units (SI) +/* ------------------------------------------------------------------------------------- */ + +using units::KB; ///< Kilobyte +using units::MB; ///< Megabyte +using units::GB; ///< Gigabyte +using units::TB; ///< Terabyte + +// ===================================================================================== // +// <> DigitalSize | CAST OPERATIONS +// ===================================================================================== // + +/*! + * @brief + * Converts a digital size value to different units. + * + * @note + * Values that cannot be represented exact in the target + * units are truncated towards zero. + * + * @return + * Source units expressed in the target units + */ +template +constexpr To_Units size_cast(const From_Units& source) noexcept +{ + return units::DigitalSizeCast::cast(source); +} + +// ===================================================================================== // +// <> DigitalSize | USER-DEFINED LITERALS +// ===================================================================================== // + +/*! + * @brief + * User-defined literals for digital size units. + */ +namespace digital_size::literals { + +/*! + * @brief + * Byte literal. + */ +constexpr Bytes operator""_Bytes(unsigned long long value) noexcept +{ + return Bytes{static_cast(value)}; +} + +/* ------------------------------------------------------------------------------------- */ +// > Binary Digital Size UDL's (IEC) +/* ------------------------------------------------------------------------------------- */ + +/*! + * @brief + * Kibibyte literal. + */ +constexpr KiB operator""_KiB(unsigned long long value) noexcept +{ + return KiB{ static_cast(value) }; +} + +/*! + * @brief + * Mebibyte literal. + */ +constexpr MiB operator""_MiB(unsigned long long value) noexcept +{ + return MiB{ static_cast(value) }; +} + +/*! + * @brief + * Gibibyte literal. + */ +constexpr GiB operator""_GiB(unsigned long long value) noexcept +{ + return GiB{ static_cast(value) }; +} + +/*! + * @brief + * Tebibyte literal. + */ +constexpr TiB operator""_TiB(unsigned long long value) noexcept +{ + return TiB{ static_cast(value) }; +} + +/* ------------------------------------------------------------------------------------- */ +// > Decimal Digital Size UDL's (SI) +/* ------------------------------------------------------------------------------------- */ + +/*! + * @brief + * Kilobyte literal. + */ +constexpr KB operator""_KB(unsigned long long value) noexcept +{ + return KB{static_cast(value)}; +} + +/*! + * @brief + * Megabyte literal. + */ +constexpr MB operator""_MB(unsigned long long value) noexcept +{ + return MB{static_cast(value)}; +} + +/*! + * @brief + * Gigabyte literal. + */ +constexpr GB operator""_GB(unsigned long long value) noexcept +{ + return GB{static_cast(value)}; +} + +/*! + * @brief + * Terabyte literal. + */ +constexpr TB operator""_TB(unsigned long long value) noexcept +{ + return TB{static_cast(value)}; +} + +} + +} + +#endif // CHEVRON_LIB_HDR_EXPLICIT_UNITS_INCLUDE_H_ diff --git a/include/chevron/utility/bits/alignment.hpp b/include/chevron/utility/bits/alignment.hpp new file mode 100644 index 0000000..3d7c5db --- /dev/null +++ b/include/chevron/utility/bits/alignment.hpp @@ -0,0 +1,120 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file alignment.hpp + * + * @brief + * Generic alignment utilities for sizes, offsets, and addresses. + * + * @author + * Jamon T. Bailey + * + * @date 04-18-2026 + */ + +#ifndef CHEVRON_LIB_HDR_GENERAL_ALIGNMENT_UTILITIES_H_ +#define CHEVRON_LIB_HDR_GENERAL_ALIGNMENT_UTILITIES_H_ + +#include +#include +#include + +namespace chevron::bits +{ + +/*! + * @brief + * Aligns a size or offset value upward to the nearest + * multiple of alignment. + * + * @note + * If the provided value is already a multiple of the + * alignment, it is returned unchanged. + * + * @return + * Value rounded up to nearest multiple of alignment + */ +constexpr size_t alignUp(const size_t value, const size_t alignment) +{ + if (alignment == 0) + throw std::invalid_argument{"alignUp(): Alignment must be non-zero."}; + + const size_t remainder = value % alignment; + + if (remainder == 0) + return value; + + return value + (alignment - remainder); +} + +/*! + * @brief + * Aligns a pointer upward to the nearest address that + * is a multiple of alignment. + * + * @note + * If the provided address is already a multiple of the + * alignment, it is returned unchanged. + * + * @return + * Pointer rounded up to nearest multiple of alignment + */ +template +T* alignUp(const T* ptr, const size_t alignment) +{ + const uintptr_t address = reinterpret_cast(ptr); + const uintptr_t aligned = static_cast( + alignUp(static_cast(address), alignment) + ); + return reinterpret_cast(aligned); +} + +/*! + * @brief + * Aligns a size or offset value downward to the nearest + * multiple of alignment. + * + * @note + * If the provided value is already a multiple of the + * alignment, it is returned unchanged. + * + * @return + * Value rounded down to nearest multiple of alignment + */ +constexpr size_t alignDown(const size_t value, const size_t alignment) +{ + if (alignment == 0) + throw std::invalid_argument{"alignDown(): Alignment must be non-zero."}; + + return value - (value % alignment); +} + +/*! + * @brief + * Aligns a pointer downward to the nearest address that + * is a multiple of alignment. + * + * @note + * If the provided address is already a multiple of the + * alignment, it is returned unchanged. + * + * @return + * Pointer rounded down to nearest multiple of alignment + */ +template +T* alignDown(const T* ptr, const size_t alignment) +{ + const uintptr_t address = reinterpret_cast(ptr); + const uintptr_t aligned = static_cast( + alignDown(static_cast(address), alignment) + ); + return reinterpret_cast(aligned); +} + +} + +#endif // CHEVRON_LIB_HDR_GENERAL_ALIGNMENT_UTILITIES_H_ diff --git a/include/chevron/utility/bits/bit_inspect.hpp b/include/chevron/utility/bits/bit_inspect.hpp new file mode 100644 index 0000000..f6b7ae5 --- /dev/null +++ b/include/chevron/utility/bits/bit_inspect.hpp @@ -0,0 +1,40 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file bit_inspect.hpp + * + * @brief + * Compile-time bit pattern inspection primitives. + * + * @author + * Jamon T. Bailey + * + * @date 04-18-2026 + */ + +#ifndef CHEVRON_LIB_HDR_BIT_INSPECTION_UTILITIES_H_ +#define CHEVRON_LIB_HDR_BIT_INSPECTION_UTILITIES_H_ + +#include +#include + +namespace chevron::bits +{ + +// TODO: INCOMPLETE HEADER!!! + +// NOTE: 'std::unsigned_integral' not reliable, need local impl + +// template +// constexpr int countLeadingZeros(const UIntT value) noexcept; + +// template +// constexpr int countTrailingZeros(const UIntT value) noexcept; + +} + +#endif // CHEVRON_LIB_HDR_BIT_INSPECTION_UTILITIES_H_ diff --git a/include/chevron/utility/bits/powers.hpp b/include/chevron/utility/bits/powers.hpp new file mode 100644 index 0000000..fcdcd88 --- /dev/null +++ b/include/chevron/utility/bits/powers.hpp @@ -0,0 +1,244 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file powers.hpp + * + * @brief + * Predicates and rounding operations for power-of-two values. + * + * @author + * Jamon T. Bailey + * + * @date 04-19-2026 + */ + +#ifndef CHEVRON_LIB_HDR_POWER_OF_TWO_UTILITIES_H_ +#define CHEVRON_LIB_HDR_POWER_OF_TWO_UTILITIES_H_ + +#include +#include +#include +#include + +namespace chevron::bits +{ + +// ===================================================================================== // +// <> POWER-OF-TWO UTILITIES +// ===================================================================================== // + +/*! + * @brief + * Determines maximum power of 2 exponent representable by + * the provided unsigned integer type. + */ +template +constexpr UIntT max_power_of_two_exponent = []() { + return std::numeric_limits::digits - 1; +}(); + +/*! + * @brief + * Determines if provided unsigned integer is a power of 2. + * + * @note + * Note that `1` is considered a power of 2 because 2^0 is + * equal to 1. Additionally, `0` is **NOT** considered a + * power of 2 because no integer exponent produces a value + * of zero with 2 as the base. + * + * @return + * True if provided value is a power of 2 + */ +template +constexpr bool isPowerOfTwo(UIntT value) noexcept { + return std::has_single_bit(value); +} + +/*! + * @brief + * Rounds provided value up to next power of 2. + * + * @note + * If the provided value is already a power of 2, it is + * returned unchanged. Additionally, the smallest power + * of 2 is 1, so `powerOfTwoCeil(0)` returns `1` by + * convention. + * + * @return + * Next power of 2 + */ +template +constexpr UIntT powerOfTwoCeil(UIntT value) { + constexpr UIntT maxPower = max_power_of_two_exponent; + + if (value > maxPower) { + throw std::overflow_error{ + "powerOfTwoCeil(): Value exceeds the maximum representable " + "power of 2 for the target unsigned integral type." + }; + } + + return std::bit_ceil(value); +} + +/*! + * @brief + * Rounds provided value down to previous power of 2. + * + * @note + * If the provided value is already a power of 2, it is + * returned unchanged. Additionally, the smallest power + * of 2 is 1. + * + * @return + * Previous power of 2 + */ +template +constexpr UIntT powerOfTwoFloor(UIntT value) { + if (value == 0) { + throw std::overflow_error{ + "powerOfTwoFloor(): Zero value has no previous power of 2." + }; + } + + return std::bit_floor(value); + // TODO: Are we really going to throw over this? Think about this. +} + +// ===================================================================================== // +// <> POWER-OF-TEN UTILITIES +// ===================================================================================== // + +/*! + * @brief + * Determines maximum power of 10 exponent representable + * by the provided unsigned integer type. + */ +template +constexpr UIntT max_power_of_ten_exponent = []() { + constexpr UIntT uintMax = std::numeric_limits::max(); + UIntT exponent = 0; + UIntT value = 1; + + while (value <= uintMax / 10) { + value *= 10; + ++exponent; + } + + return exponent; +}(); + +/*! + * @brief + * Determines if provided unsigned integer is a power of 10. + * + * @note + * Note that `1` is considered a power of 10 because 10^0 is + * equal to 1. Additionally, `0` is **NOT** considered a + * power of 10 because no integer exponent produces a value + * of zero with 10 as the base. + * + * @return + * True if provided value is a power of 10 + */ +template +constexpr bool isPowerOfTen(UIntT value) noexcept { + if (value == 0 || value % 2 != 0) + return false; + + while (value > 1) { + const bool multipleOfTen = value % 10 != 0; + + switch (multipleOfTen) { + case true: + return false; + + default: + value /= 10; + } + } + + return true; +} + +/*! + * @brief + * Rounds provided value up to next power of 10. + * + * @note + * If the provided value is already a power of 10, it is + * returned unchanged. Additionally, the smallest power + * of 10 is 1, so `powerOfTenCeil(0)` returns `1` by + * convention. + * + * @return + * Next power of 10 + */ +template +constexpr UIntT powerOfTenCeil(UIntT value) { + if (value == 0) + return UIntT{value}; + + constexpr UIntT uintMax = std::numeric_limits::max(); + UIntT accumulator = 1; + + while (accumulator < value) { + if (accumulator > uintMax / 10) { + throw std::overflow_error{ + "powerOfTenCeil(): Value exceeds the maximum representable " + "power of ten for the target unsigned integral type." + }; + } + + accumulator *= 10; + } + + return accumulator; +} + +/*! + * @brief + * Rounds provided value down to previous power of 10. + * + * @note + * If the provided value is already a power of 10, it is + * returned unchanged. Additionally, the smallest power + * of 10 is 1. + * + * @return + * Previous power of 10 + */ +template +constexpr UIntT powerOfTenFloor(UIntT value) { + if (value == 0) { + throw std::overflow_error{ + "powerOfTenFloor(): Zero value has no previous power of 10." + }; + } + + constexpr UIntT uintMax = std::numeric_limits::max(); + UIntT accumulator = 1; + + while (accumulator <= value) { + if (accumulator > uintMax / 10) + return accumulator; + + const UIntT next = accumulator * 10; + + if (next > value) + return accumulator; + + accumulator = next; + } + + return accumulator; +} + +} + +#endif // CHEVRON_LIB_HDR_POWER_OF_TWO_UTILITIES_H_ diff --git a/include/chevron/utility/function/callable.hpp b/include/chevron/utility/function/callable.hpp index 1f95c12..550cf7b 100644 --- a/include/chevron/utility/function/callable.hpp +++ b/include/chevron/utility/function/callable.hpp @@ -181,9 +181,9 @@ Callable(ClassType*, ReturnT (ClassType::*)(ArgsT...) const) /*! @details Lambda and functor deduction guide. */ template Callable(Function&&) -> Callable< - typename model::traits::callable_signature>::ReturnType, - model::traits::to_funcargs_t< - typename model::traits::callable_signature>::ArgsTuple>>; + typename func::traits::callable_signature>::ReturnType, + func::traits::to_funcargs_t< + typename func::traits::callable_signature>::ArgsTuple>>; // TODO: Lambda and functor deduction guide only works // when directly naming `Callable` with it's fully diff --git a/include/chevron/utility/function/concepts.hpp b/include/chevron/utility/function/concepts.hpp index f4ff479..ac67560 100644 --- a/include/chevron/utility/function/concepts.hpp +++ b/include/chevron/utility/function/concepts.hpp @@ -17,13 +17,13 @@ #include #include -namespace chevron::model::concepts +namespace chevron::func::concepts { /*! @brief Concept that validates indexing into function parameters. */ template -concept is_valid_args_index = Index >= 0 && Index < sizeof...(ArgsT); +concept valid_arguments_index = Index >= 0 && Index < sizeof...(ArgsT); -} // namespace chevron::model::concepts +} // namespace chevron::func::concepts #endif // CHEVRON_LIB_HDR_FUNCTION_CONCEPTS_H_ diff --git a/include/chevron/utility/function/func_args.hpp b/include/chevron/utility/function/func_args.hpp index 78bf340..e5e3098 100644 --- a/include/chevron/utility/function/func_args.hpp +++ b/include/chevron/utility/function/func_args.hpp @@ -78,7 +78,7 @@ class FuncArgs { /*! @brief Get argument at specified index. */ template - requires(model::concepts::is_valid_args_index) + requires(func::concepts::valid_arguments_index) [[nodiscard]] constexpr decltype(auto) get() noexcept { return std::get(this->args); @@ -86,7 +86,7 @@ class FuncArgs { /*! @brief Get argument at specified index. */ template - requires(model::concepts::is_valid_args_index) + requires(func::concepts::valid_arguments_index) [[nodiscard]] constexpr decltype(auto) get() const noexcept { return std::get(this->args); @@ -116,7 +116,7 @@ class FuncArgs { // <> chevron::FuncArgs | TYPE TRAIT UTILITIES // ===================================================================================== // -namespace model::traits +namespace func::traits { /*! @brief Function arguments structure conversion utility. */ @@ -133,7 +133,7 @@ struct to_funcargs> { template using to_funcargs_t = to_funcargs::type; -} // namespace model::traits +} // namespace func::traits // ===================================================================================== // // <> chevron::FuncArgs | DEDUCTION GUIDES diff --git a/include/chevron/utility/function/type_traits.hpp b/include/chevron/utility/function/type_traits.hpp index bd5ebe2..673abe5 100644 --- a/include/chevron/utility/function/type_traits.hpp +++ b/include/chevron/utility/function/type_traits.hpp @@ -18,7 +18,7 @@ #include #include -namespace chevron::model::traits +namespace chevron::func::traits { /*! @brief Callable entity signature extraction utility. */ @@ -67,6 +67,6 @@ struct callable_signature { using FuncType = ReturnT (*)(ArgsT...); }; -} // namespace chevron::model::traits +} // namespace chevron::func::traits #endif // CHEVRON_LIB_HDR_FUNCTION_TYPE_TRAITS_H_ diff --git a/include/chevron/utility/math/algebra.hpp b/include/chevron/utility/math/algebra.hpp new file mode 100644 index 0000000..309496b --- /dev/null +++ b/include/chevron/utility/math/algebra.hpp @@ -0,0 +1,61 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file algebra.hpp + * + * @brief + * Algebraic computation utilities. + * + * @author + * Jamon T. Bailey + * + * @date 04-18-2026 + */ + +#ifndef CHEVRON_LIB_HDR_ALGEBRAIC_COMPUTATION_H_ +#define CHEVRON_LIB_HDR_ALGEBRAIC_COMPUTATION_H_ + +#include + +namespace chevron::math +{ + +/* ------------------------------------------------------------------------------------- */ +// > Exponents +/* ------------------------------------------------------------------------------------- */ + +/*! + * @brief + * Computes integral exponentation on provided base and + * exponent. + * + * @return + * = (base^expon) + */ +constexpr uint64_t exponent(const uint64_t base, const uint64_t expon) +{ + uint64_t result = 1; + + for (uint64_t i = 0; i < expon; ++i) + result *= base; + + return result; +} + +/*! + * @brief + * Computes integral exponentation. + * + * @return + * = (Base^Expon) + */ +template +constexpr uint64_t exponent_v = exponent(Base, Expon); + +} + +#endif // CHEVRON_LIB_HDR_ALGEBRAIC_COMPUTATION_H_ diff --git a/src/process/CMakeLists.txt b/src/process/CMakeLists.txt index 83c1a62..c421bfb 100644 --- a/src/process/CMakeLists.txt +++ b/src/process/CMakeLists.txt @@ -6,6 +6,11 @@ target_sources( ${CHEVRON_MAIN_BINARY_NAME} + PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/memory/mem_pool_config.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/memory/proc_mem_pool.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/memory/memory_core.cpp" + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/thread/thread_engine.cpp" ) diff --git a/src/process/memory/mem_pool_config.cpp b/src/process/memory/mem_pool_config.cpp new file mode 100644 index 0000000..39b9722 --- /dev/null +++ b/src/process/memory/mem_pool_config.cpp @@ -0,0 +1,47 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file mem_pool_config.cpp + * + * @brief + * // TODO: INCOMPLETE DOC STRING!!! + * + * @author + * Jamon T. Bailey + * + * @date 04-14-2026 + */ + +#include +#include "chevron/process/memory/mem_pool_config.hpp" + +// ===================================================================================== // +// <> chevron::process::MemoryPoolConfig | [PUBLIC] MEMBER METHODS +// ===================================================================================== // + +bool chevron::process::MemoryPoolConfig::isValid() const noexcept +{ + return validate(nullptr); +} + +void chevron::process::MemoryPoolConfig::isValidOrThrow() const +{ + const char* reason = nullptr; + + if (!validate(&reason)) + throw std::invalid_argument(reason); +} + +// ===================================================================================== // +// <> chevron::process::MemoryPoolConfig | [PRIVATE] MEMBER METHODS +// ===================================================================================== // + +bool chevron::process::MemoryPoolConfig::validate(const char** reason) const noexcept +{ + // TODO: INCOMPLETE IMPLEMENTATION!!! + return false; +} diff --git a/src/process/memory/memory_core.cpp b/src/process/memory/memory_core.cpp new file mode 100644 index 0000000..f86c654 --- /dev/null +++ b/src/process/memory/memory_core.cpp @@ -0,0 +1,21 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file memory_core.cpp + * + * @brief + * // TODO: INCOMPLETE DOC STRING!!! + * + * @author + * Jamon T. Bailey + * + * @date 04-01-2026 + */ + +#include "chevron/process/memory/memory_core.hpp" + +// TODO : INCOMPLETE IMPLEMENTATION!!! diff --git a/src/process/memory/proc_mem_pool.cpp b/src/process/memory/proc_mem_pool.cpp new file mode 100644 index 0000000..bbde4f2 --- /dev/null +++ b/src/process/memory/proc_mem_pool.cpp @@ -0,0 +1,21 @@ + +// Copyright (C) 2026 by Jamon T. Bailey and InfinSys, LLC. All rights reserved. +// Released under the terms of the GNU Affero General Public License version 3 + +// [ISJTB-CXX-XL20260108-000003] + +/*! + * @file proc_mem_pool.cpp + * + * @brief + * // TODO: INCOMPLETE DOC STRING!!! + * + * @author + * Jamon T. Bailey + * + * @date 04-14-2026 + */ + +#include "chevron/process/memory/proc_mem_pool.hpp" + + // TODO : INCOMPLETE IMPLEMENTATION!!! diff --git a/tests/cli/dev_exe.cpp b/tests/cli/dev_exe.cpp index 8463f7a..0dd48f6 100644 --- a/tests/cli/dev_exe.cpp +++ b/tests/cli/dev_exe.cpp @@ -3,7 +3,12 @@ #include #include "chevron/function.hpp" +#include "chevron/units.hpp" +#include "chevron/common/macro_defs.h" #include "chevron/process/thread/thread_engine.hpp" +#include "chevron/process/memory/memory_core.hpp" +#include "chevron/utility/bits/alignment.hpp" +#include "chevron/utility/bits/powers.hpp" int main(int argc, char* argv[]) { @@ -11,6 +16,25 @@ int main(int argc, char* argv[]) // // Start... + using namespace chevron::digital_size::literals; + + constexpr chevron::MiB blockSize = 16_MiB; + constexpr chevron::MiB chunkSize = blockSize * 32; + constexpr size_t maxOSAllocs = 8; + constexpr chevron::GiB budgetMax = chevron::size_cast( + chunkSize * maxOSAllocs + ); + + chevron::process::MemoryPoolConfig config{}; + + config.block_size = blockSize; + config.chunk_size = chunkSize; + config.block_alignment = sizeof(std::max_align_t); + config.budget_ceiling = budgetMax; + config.initial_thread_blocks = 2; + config.max_thread_blocks = 12; + + // // //\\// @@ -22,6 +46,22 @@ int main(int argc, char* argv[]) /* * :: Chevron Notes :: * + * [ TO-DO ] + * -> Start applying export macros to appropriate symbols + * -> Figure out how exception and error codes will be integrated + * * [ Function Utilities Notes ] * -> Static callable type `Func`? (No heap alloc) + * + * [ Units Facility Notes ] + * -> Length measure units? (i.e. milimeters, centimeters, meters, inches, feet, yards) + * -> (these can use device display info to determine pixel counts?) + * -> Time measure units? (i.e. miliseconds, seconds, minutes, hours, days, months, years) */ + +// Potential Debug Mode Bad Address Signal: +// 0xDEAD2BAD == 3,735,890,861 +// 0xDEA110C == 233,443,596 +// 0xDEA110CA7ED +// 0xDEA110CA7ED64B (a.k.a -> DEA110CA7ED 64 B [Deallocated 64 Bit]) +// == 62,664,538,318,624,331