Skip to content

Commit

Permalink
Moved some memory utilities from Anyness; Now dispatching to Langulus…
Browse files Browse the repository at this point in the history
…::Fractalloc
  • Loading branch information
Epixu committed Aug 21, 2023
1 parent 14add61 commit e8d2b6b
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
build:
strategy:
matrix:
dependents: [Logger, RTTI, SIMD, Anyness, Flow, Entity, Math]
dependents: [Logger, RTTI, SIMD, Fractalloc, Anyness, Flow, Math, Entity]
name: Trigger Langulus::${{matrix.dependents}}'s workflow
runs-on: ubuntu-latest
steps:
Expand Down
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
cmake_minimum_required(VERSION 3.24)
project(LangulusCore)
project(LangulusCore
VERSION 1.0.0
DESCRIPTION "Langulus core library"
HOMEPAGE_URL https://langulus.com
LANGUAGES CXX
)

add_library(LangulusCore INTERFACE)
target_compile_features(LangulusCore INTERFACE cxx_std_20)
Expand Down
192 changes: 192 additions & 0 deletions source/Core/Utilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,5 +282,197 @@ namespace Langulus
const auto r = v % alignment;
return r > 0 ? v + (alignment - r) : v;
}

/// Wrapper for memcpy
/// @tparam TO - destination memory type (deducible)
/// @tparam FROM - source memory type (deducible)
/// @param to - [out] destination memory
/// @param from - source of data to copy
template<class TO, class FROM>
LANGULUS(INLINED)
void CopyMemory(TO* to, const FROM* from) noexcept {
static_assert(CT::Void<TO> || CT::Sparse<TO> || CT::POD<TO> || ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(you can suppress this error by casting pointer to void*)");

static_assert(CT::Void<TO> || (CT::Same<TO, FROM> && CT::Sparse<TO> == CT::Sparse<FROM>),
"TO and FROM must be the exact same types"
"(you can suppress this error by casting pointer to void*)");

if constexpr (CT::Void<TO>)
LANGULUS_ERROR("Bytecount not specified when copying void pointers");

::std::memcpy(
static_cast<void*>(to),
static_cast<const void*>(from),
sizeof(TO)
);
}

/// Wrapper for memcpy
/// @tparam TO - destination memory type (deducible)
/// @tparam FROM - source memory type (deducible)
/// @param to - [out] destination memory
/// @param from - source of data to copy
/// @param count - number of elements to copy
/// @attention count becomes bytecount, when TO is void
template<class TO, class FROM>
LANGULUS(INLINED)
void CopyMemory(TO* to, const FROM* from, const Count& count) noexcept {
static_assert(CT::Void<TO> || CT::Sparse<TO> || CT::POD<TO> || ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(you can suppress this error by casting pointer to void*)");

static_assert(CT::Void<TO> || (CT::Same<TO, FROM> && CT::Sparse<TO> == CT::Sparse<FROM>),
"TO and FROM must be the exact same types"
"(you can suppress this error by casting pointer to void*)");

if constexpr (CT::Void<TO>) {
::std::memcpy(
static_cast<void*>(to),
static_cast<const void*>(from),
count
);
}
else {
::std::memcpy(
static_cast<void*>(to),
static_cast<const void*>(from),
sizeof(TO) * count
);
}
}

/// Wrapper for memset
/// @tparam TO - destination memory type (deducible)
/// @tparam FILLER - value to fill in with
/// @param to - [out] destination memory
template<int FILLER, class TO>
LANGULUS(INLINED)
void FillMemory(TO* to) noexcept {
static_assert(CT::Void<TO> || CT::Sparse<TO> || CT::POD<TO> || ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(you can suppress this error by casting to void*)");

static_assert(FILLER || CT::Nullifiable<TO> || CT::Void<TO> || CT::Sparse<TO> || CT::Fundamental<TO>,
"Filling with zeroes requires the type to be reflected as nullifiable, "
"or be a pointer/fundamental (you can suppress this error by casting to void*)");

if constexpr (CT::Void<TO>)
LANGULUS_ERROR("Bytecount not specified when filling void pointer");

::std::memset(static_cast<void*>(to), FILLER, sizeof(TO));
}

/// Wrapper for memset
/// @tparam TO - destination memory type (deducible)
/// @tparam FILLER - value to fill in with
/// @param to - [out] destination memory
/// @param count - number of elements to fill
/// @attention count becomes bytecount, when TO is void
template<int FILLER, class TO>
LANGULUS(INLINED)
void FillMemory(TO* to, const Count& count) noexcept {
static_assert(CT::Void<TO> || CT::Sparse<TO> || CT::POD<TO> || ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(you can suppress this error by casting to void*)");

static_assert(FILLER || CT::Nullifiable<TO> || CT::Void<TO> || CT::Sparse<TO> || CT::Fundamental<TO>,
"Filling with zeroes requires the type to be reflected as nullifiable, "
"or be a pointer/fundamental (you can suppress this error by casting to void*)");

if constexpr (CT::Void<TO>)
::std::memset(static_cast<void*>(to), FILLER, count);
else
::std::memset(static_cast<void*>(to), FILLER, sizeof(TO) * count);
}

/// Wrapper for memset 0
/// @tparam TO - destination memory type (deducible)
/// @param to - [out] destination memory
template<class TO>
LANGULUS(INLINED)
void ZeroMemory(TO* to) noexcept {
return FillMemory<0>(to);
}

/// Wrapper for memset 0
/// @tparam TO - destination memory type (deducible)
/// @param to - [out] destination memory
/// @param count - number of elements to fill
/// @attention count becomes bytecount, when TO is void
template<class TO>
LANGULUS(INLINED)
void ZeroMemory(TO* to, const Count& count) noexcept {
return FillMemory<0>(to, count);
}

/// Wrapper for memmove
/// @tparam TO - destination memory type (deducible)
/// @tparam FROM - source memory type (deducible)
/// @param to - [out] destination memory
/// @param from - source of data to move
template<class TO, class FROM>
LANGULUS(INLINED)
void MoveMemory(TO* to, const FROM* from) noexcept {
static_assert(CT::Void<TO> || CT::Sparse<TO> || CT::POD<TO> || ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(You can suppress this error by casting pointer to void*)");

static_assert(CT::Void<TO> || (CT::Same<TO, FROM> && CT::Sparse<TO> == CT::Sparse<FROM>),
"TO and FROM must be the exact same types"
"(you can suppress this error by casting pointer to void*)");

if constexpr (CT::Void<TO>)
LANGULUS_ERROR("Bytecount not specified when filling void pointer");

::std::memmove(
static_cast<void*>(to),
static_cast<const void*>(from),
sizeof(TO)
);

#if LANGULUS(PARANOID)
TODO() // zero old memory, but beware - `from` and `to` might overlap
#endif
}

/// Wrapper for memmove
/// @tparam TO - destination memory type (deducible)
/// @tparam FROM - source memory type (deducible)
/// @param to - [out] destination memory
/// @param from - source of data to move
/// @param count - number of elements to move
/// @attention count becomes bytecount, when TO is void
template<class TO, class FROM>
LANGULUS(INLINED)
void MoveMemory(TO* to, const FROM* from, const Count& count) noexcept {
static_assert(CT::Void<TO> || CT::Sparse<TO> || CT::POD<TO> || ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(You can suppress this error by casting pointer to void*)");

static_assert(CT::Void<TO> || (CT::Same<TO, FROM> && CT::Sparse<TO> == CT::Sparse<FROM>),
"TO and FROM must be the exact same types"
"(you can suppress this error by casting pointer to void*)");

if constexpr (CT::Void<TO>) {
::std::memmove(
static_cast<void*>(to),
static_cast<const void*>(from),
count
);
}
else {
::std::memmove(
static_cast<void*>(to),
static_cast<const void*>(from),
sizeof(TO) * count
);
}

#if LANGULUS(PARANOID)
TODO() // zero old memory, but beware - `from` and `to` might overlap
#endif
}

} // namespace Langulus

0 comments on commit e8d2b6b

Please sign in to comment.