Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

allocator concept requirements #26

Merged
merged 1 commit into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions radiant/Memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#pragma once

#include "radiant/TotallyRad.h"
#include "radiant/TypeTraits.h"

//
// Users of Radiant may define their own default allocator. Radiant itself
Expand Down Expand Up @@ -123,4 +124,19 @@ class Allocator
};
#endif

//
// Radiant allocator concept requires:
// - Destruction does not throw.
// - Copying does not throw.
// - Moving does not throw.
// - Freeing memory does not throw.
//
template <typename T>
RAD_INLINE_VAR constexpr bool AllocatorRequires =
(IsNoThrowDtor<T> && //
IsNoThrowCopyCtor<T> && IsNoThrowCopyAssign<T> && //
IsNoThrowMoveCtor<T> && IsNoThrowMoveAssign<T> &&
noexcept(DeclVal<T>().Free(nullptr)) &&
noexcept(DeclVal<T>().FreeBytes(nullptr)));

} // namespace rad
4 changes: 2 additions & 2 deletions radiant/Result.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,8 @@ class RAD_NODISCARD Result final : private detail::ResultStorage<T, E>
using typename StorageType::OkType;
using typename StorageType::ErrType;

RAD_S_ASSERT_NOTHROW_MOVE((IsNoThrowMoveCtor<T> && IsNoThrowMoveAssign<T> &&
IsNoThrowMoveCtor<E> && IsNoThrowMoveAssign<E>));
RAD_S_ASSERT_NOTHROW_MOVE_T(T);
RAD_S_ASSERT_NOTHROW_MOVE_T(E);

constexpr Result() noexcept
: StorageType(ResultEmptyTag)
Expand Down
6 changes: 6 additions & 0 deletions radiant/SharedPtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ class PtrBlock final : public PtrBlockBase
using ValueType = T;
using PairType = EmptyOptimizedPair<AllocatorType, ValueType>;

RAD_S_ASSERT_ALLOCATOR_REQUIRES_T(TAlloc);

template <typename... TArgs>
PtrBlock(const AllocatorType& alloc, TArgs&&... args) noexcept(
noexcept(PairType(alloc, Forward<TArgs>(args)...)))
Expand Down Expand Up @@ -956,6 +958,8 @@ SharedPtr<T> AllocateShared(const TAlloc& alloc, TArgs&&... args) //
noexcept(noexcept(detail::AllocateSharedImpl::AllocateShared<T, TAlloc>(
alloc, Forward<TArgs>(args)...)))
{
RAD_S_ASSERT_ALLOCATOR_REQUIRES_T(TAlloc);

return detail::AllocateSharedImpl::AllocateShared<T, TAlloc>(
alloc,
Forward<TArgs>(args)...);
Expand All @@ -972,6 +976,8 @@ template <typename T, typename TAlloc RAD_ALLOCATOR_EQ(T), typename... TArgs>
SharedPtr<T> MakeShared(TArgs&&... args) noexcept(
noexcept(AllocateShared<T>(DeclVal<TAlloc&>(), Forward<TArgs>(args)...)))
{
RAD_S_ASSERT_ALLOCATOR_REQUIRES_T(TAlloc);

TAlloc alloc;
return AllocateShared<T>(alloc, Forward<TArgs>(args)...);
}
Expand Down
24 changes: 21 additions & 3 deletions radiant/TotallyRad.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ inline bool DoAssert(const char* Assertion, const char* File, int Line)
#endif

//
// Enables assertions the move operations do not throw exceptions.
// Enables assertions that move operations do not throw exceptions.
//
// Core Guideline: A throwing move violates most people’s reasonable
// assumptions. A non-throwing move will be used more efficiently by
Expand All @@ -282,15 +282,33 @@ inline bool DoAssert(const char* Assertion, const char* File, int Line)
#if RAD_ENABLE_NOTHROW_MOVE_ASSERTIONS
#define RAD_S_ASSERT_NOTHROW_MOVE(x) \
RAD_S_ASSERTMSG(x, "move operations should not throw")

#define RAD_S_ASSERT_NOTHROW_MOVE_T(x) \
RAD_S_ASSERTMSG(IsNoThrowMoveCtor<T>&& IsNoThrowMoveAssign<T>, \
RAD_S_ASSERTMSG(IsNoThrowMoveCtor<x>&& IsNoThrowMoveAssign<x>, \
"move operations should not throw")
#else
#define RAD_S_ASSERT_NOTHROW_MOVE(x) RAD_S_ASSERT(true)
#define RAD_S_ASSERT_NOTHROW_MOVE_T(x) RAD_S_ASSERT(true)
#endif

//
// Enables assertions that allocators meet the Radiant allocator concept
// requirements.
//
// See: rad::AllocatorRequires
//
#ifndef RAD_ENABLE_ALLOCATOR_REQUIRES_ASSERTIONS
#define RAD_ENABLE_ALLOCATOR_REQUIRES_ASSERTIONS 1
#endif
#if RAD_ENABLE_ALLOCATOR_REQUIRES_ASSERTIONS
#define RAD_S_ASSERT_ALLOCATOR_REQUIRES(x) \
RAD_S_ASSERTMSG(x, "allocator requirements not met")
#define RAD_S_ASSERT_ALLOCATOR_REQUIRES_T(x) \
RAD_S_ASSERTMSG(AllocatorRequires<x>, "allocator requirements not met")
#else
#define RAD_S_ASSERT_ALLOCATOR_REQUIRES(x) RAD_S_ASSERT(true)
#define RAD_S_ASSERT_ALLOCATOR_REQUIRES_T(x) RAD_S_ASSERT(true)
#endif

#define RAD_NOT_COPYABLE(x) \
x(x const&) = delete; \
x& operator=(x const&) = delete
Expand Down
2 changes: 1 addition & 1 deletion radiant/TypeWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class TypeWrapper<T, false>

using Type = T;

RAD_S_ASSERT_NOTHROW_MOVE((IsNoThrowMoveCtor<T> && IsNoThrowMoveAssign<T>));
RAD_S_ASSERT_NOTHROW_MOVE_T(T);

template <typename U = T, EnIf<IsDefaultCtor<U>, int> = 0>
constexpr TypeWrapper() noexcept(IsNoThrowDefaultCtor<T>)
Expand Down
2 changes: 1 addition & 1 deletion radiant/Vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class Vector final
using OtherType = Vector<T, OtherTAllocator, OtherTInlineCount>;

RAD_S_ASSERT_NOTHROW_MOVE_T(T);
RAD_S_ASSERT_NOTHROW_MOVE_T(TAllocator);
RAD_S_ASSERT_ALLOCATOR_REQUIRES_T(TAllocator);

~Vector()
{
Expand Down
Loading