-
Notifications
You must be signed in to change notification settings - Fork 2
test realloc behaviour and allocator equality #3
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -137,13 +137,16 @@ class linear_memory_resource { | |
| } | ||
|
|
||
| // Returns a pointer to the arena/parent allocation. | ||
| void* data() const { return reinterpret_cast<void*>(m_begin); } | ||
| [[nodiscard]] void* data() const { return reinterpret_cast<void*>(m_begin); } | ||
|
|
||
| // Returns the total number of bytes allocated within the arena | ||
| size_t size() const { return m_next - reinterpret_cast<uintptr_t>(m_begin); } | ||
| [[nodiscard]] size_t size() const { return m_next - reinterpret_cast<uintptr_t>(m_begin); } | ||
|
|
||
| // Returns the size of the arena/parent allocation | ||
| size_t capacity() const { return m_end - reinterpret_cast<uintptr_t>(m_begin); } | ||
| [[nodiscard]] size_t capacity() const { return m_end - reinterpret_cast<uintptr_t>(m_begin); } | ||
|
|
||
| // Provide public access to parent allocator. Primarily used for testing. | ||
| [[nodiscard]] ParentAllocator& parent() { return m_parent; } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure proper documentation for the Adding a brief comment describing the purpose and usage of the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would you suggest? For reference, this is the equivalent of e.g. upstream_resource in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @pknowles, based on the reference to /**
* Returns a reference to the parent allocator.
* This method provides access to the underlying allocator used by this `linear_memory_resource`,
* similar to how `upstream_resource` provides access to the upstream memory resource in `std::pmr::monotonic_buffer_resource`.
* It is primarily used for testing and debugging purposes, where direct access to the underlying allocator is necessary.
*/
[[nodiscard]] ParentAllocator& parent() { return m_parent; }This comment explains the purpose and usage of the |
||
|
|
||
| private: | ||
| ParentAllocator m_parent; | ||
|
|
@@ -176,30 +179,46 @@ class memory_resource_ref { | |
| return m_resource->deallocate(static_cast<void*>(p), n); | ||
| } | ||
|
|
||
| bool operator==(const memory_resource_ref& other) const { | ||
| [[nodiscard]] constexpr T* reallocate(T* ptr, std::size_t bytes) | ||
| requires realloc_memory_resource<MemoryResource> | ||
| { | ||
| return static_cast<T*>(m_resource->reallocate(ptr, bytes)); | ||
| } | ||
|
Comment on lines
+182
to
+186
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure proper documentation for the Adding a brief comment describing the purpose and usage of the |
||
|
|
||
| [[nodiscard]] constexpr size_t max_size() const | ||
| requires has_max_size<MemoryResource> | ||
| { | ||
| return m_resource->max_size(); | ||
| } | ||
|
Comment on lines
+188
to
+192
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure proper documentation for the Adding a brief comment describing the purpose and usage of the
Comment on lines
+182
to
+192
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure proper documentation for new methods Adding a brief comment describing the purpose and usage of these methods would enhance code readability and maintainability. |
||
|
|
||
| template <trivially_destructible U> | ||
| [[nodiscard]] bool operator==(const memory_resource_ref<U, MemoryResource>& other) const { | ||
| return m_resource == other.m_resource; | ||
| } | ||
|
|
||
| bool operator!=(const memory_resource_ref& other) const { | ||
| template <trivially_destructible U> | ||
| [[nodiscard]] bool operator!=(const memory_resource_ref<U, MemoryResource>& other) const { | ||
|
Comment on lines
+194
to
+200
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add unit tests for the templated equality and inequality operators. The changes to the equality and inequality operators are significant. Would you like me to help by adding unit tests to ensure their correct behavior? Add unit tests for the templated equality and inequality operators. The changes to the equality and inequality operators are significant. Would you like me to help by adding unit tests to ensure their correct behavior?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @pknowles, here are the unit tests for the templated equality and inequality operators in the #include <gtest/gtest.h>
#include "allocator.hpp"
class TestResource : public decodeless::memory_resource {
public:
void* allocate(size_t size, size_t alignment) override {
return ::operator new(size);
}
void deallocate(void* p, size_t size) override {
::operator delete(p);
}
};
TEST(MemoryResourceRef, Equality) {
TestResource res1, res2;
decodeless::memory_resource_ref<int, TestResource> ref1(res1);
decodeless::memory_resource_ref<float, TestResource> ref2(res1);
decodeless::memory_resource_ref<int, TestResource> ref3(res2);
// Test equality of the same resource type and instance
EXPECT_TRUE(ref1 == ref1);
// Test equality of different resource types but same instance
EXPECT_TRUE(ref1 == ref2);
// Test inequality of different instances
EXPECT_FALSE(ref1 == ref3);
}
TEST(MemoryResourceRef, Inequality) {
TestResource res1, res2;
decodeless::memory_resource_ref<int, TestResource> ref1(res1);
decodeless::memory_resource_ref<float, TestResource> ref2(res1);
decodeless::memory_resource_ref<int, TestResource> ref3(res2);
// Test inequality of the same resource type and instance
EXPECT_FALSE(ref1 != ref1);
// Test inequality of different resource types but same instance
EXPECT_FALSE(ref1 != ref2);
// Test inequality of different instances
EXPECT_TRUE(ref1 != ref3);
}These tests use a simple |
||
| return m_resource != other.m_resource; | ||
| } | ||
|
|
||
| resource_type& resource() const { return *m_resource; } | ||
| // Public access required for rebind | ||
| [[nodiscard]] resource_type& resource() const { return *m_resource; } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mark The
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is required by the rebind constructor that converts between allocators that create different types. The only alternative would probably be declaring other allocator types as friends. I'm not sure which is more widely done. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @pknowles, your approach to mark the Regarding the alternative of declaring other allocator types as friends, this is generally less common for this purpose. Using friend declarations can lead to tighter coupling between classes, which might complicate maintenance and reduce encapsulation. The use of Your current implementation is well-justified and adheres to good C++ practices. If you have any more questions or need further clarification, feel free to ask! |
||
|
|
||
| // Needed by msvc | ||
| template <class U> | ||
| struct rebind { | ||
| using other = memory_resource_ref<U, MemoryResource>; | ||
| }; | ||
|
|
||
| protected: | ||
| private: | ||
| resource_type* m_resource; | ||
| }; | ||
|
|
||
| // STL compatible allocator with an implicit linear_memory_resource memory | ||
| // resource. The need for this emphasizes why std::pmr is a thing - the | ||
| // MemoryResource would ideally not affect the type. | ||
| template <trivially_destructible T, memory_resource MemoryResource = linear_memory_resource<>> | ||
| using linear_allocator = memory_resource_ref<T, MemoryResource>; | ||
| template <trivially_destructible T, | ||
| memory_resource_or_allocator ParentAllocator = std::allocator<std::byte>> | ||
| using linear_allocator = memory_resource_ref<T, linear_memory_resource<ParentAllocator>>; | ||
|
|
||
| } // namespace decodeless | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure proper documentation for the
data()method.Adding a brief comment describing the purpose and usage of the
data()method would enhance code readability and maintainability.