-
-
Notifications
You must be signed in to change notification settings - Fork 173
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
allocators are being ignored on different constructors #539
Comments
Thanks for reporting. I'm off on vacation today, and won't be back until I return on Sep 24, but will investigate then. |
Thank you for replying @danielaparker! Have a good one and we talk when you are back ❤️ |
I also noticed that copy assignment does not poll |
@kostasrim, to address your points:
I've added a sizeable number of test cases for copy construction and move construction with Below are a few of the cases covered in the tests. Please feel free to propose additional tests, or ask for justification for expected results. #include <jsoncons/json.hpp>
#include <memory_resource>
#include <cassert>
int main()
{
using allocator_type = std::pmr::polymorphic_allocator<char>;
char buffer1[1024] = {}; // a small buffer on the stack
char* last1 = buffer1 + sizeof(buffer1);
std::pmr::monotonic_buffer_resource pool1{ std::data(buffer1), std::size(buffer1) };
allocator_type alloc1(&pool1);
char buffer2[1024] = {}; // another small buffer on the stack
char* last2 = buffer2 + sizeof(buffer2);
std::pmr::monotonic_buffer_resource pool2{ std::data(buffer2), std::size(buffer2) };
allocator_type alloc2(&pool2);
const char* long_key = "Key too long for short string";
const char* long_key_end = long_key + strlen(long_key);
const char* long_string = "String too long for short string";
const char* long_string_end = long_string + strlen(long_string);
const char* another_long_string = "Another string too long for short string";
const char* another_long_string_end = another_long_string + strlen(another_long_string);
// Construct a jsoncons::pmr::json with an allocator
jsoncons::pmr::json j1{alloc1};
assert(j1.is_object());
assert(&pool1 == j1.get_allocator().resource());
// Copy construct a jsoncons::pmr::json with a long string
jsoncons::pmr::json j2{ long_string, alloc1 };
assert(j2.is_string());
assert(&pool1 == j2.get_allocator().resource());
// Copy construct a jsoncons::pmr::json with a json long string with alloc1
jsoncons::pmr::json j3(j2);
assert(j3.is_string());
assert(j3.get_allocator() == std::allocator_traits<allocator_type>::select_on_container_copy_construction(j2.get_allocator()));
assert(j3.get_allocator() == allocator_type{});
// Move construct a jsoncons::pmr::json with a json long string with alloc1
jsoncons::pmr::json j4(std::move(j2));
assert(j4.is_string());
assert(&pool1 == j4.get_allocator().resource());
// Copy a json array having alloc2 to a json array having alloc1
jsoncons::pmr::json j5{ jsoncons::json_array_arg, alloc1 };
assert(&pool1 == j5.get_allocator().resource());
j5.push_back(long_string);
auto it = std::search(buffer1, last1, long_string, long_string_end);
assert(it != last1);
jsoncons::pmr::json j6{ jsoncons::json_array_arg, alloc2 };
assert(&pool2 == j6.get_allocator().resource());
j6.push_back(another_long_string);
it = std::search(buffer2, last2, another_long_string, another_long_string_end);
assert(it != last2);
j5 = j6;
assert(&pool1 == j5.get_allocator().resource());
it = std::search(buffer1, last1, another_long_string, another_long_string_end);
assert(j5 == j6);
// Copy a json object having alloc2 to a json number having no allocator
jsoncons::pmr::json j7{ 10 };
assert(j7.is_number());
jsoncons::pmr::json j8{ alloc2 };
assert(j8.is_object());
j8.insert_or_assign(long_key, long_string);
j7 = j8;
assert(j7.get_allocator() == std::allocator_traits<allocator_type>::select_on_container_copy_construction(j8.get_allocator()));
assert(j7.get_allocator() == allocator_type{});
// Move a json object having alloc2 to a json number having no allocator
jsoncons::pmr::json j9{ 10 };
assert(j9.is_number());
j9 = std::move(j8);
assert(&pool2 == j9.get_allocator().resource());
it = std::search(buffer2, last2, long_key, long_key_end);
assert(it != last2);
it = std::search(buffer2, last2, long_string, long_string_end);
assert(it != last2);
} |
I've added documentation Allocators that is consistent with the code that is on master. |
Hi there,
Allocators are not properly propagated on constructors. Two cases I found (not exhaustively):
Both cases (A, B) above ignore
alloc
std::pmr::polymorphic_allocator
is astateless
allocator. However, the waypmr
works is the argument to it's constructorstd::memory_resource
is a polymorphic object. So when a user wants to supply a different allocator (let's say jemalloc) they will inherit frommemory_resource
and override the methodsdo_allocate
,do_deallocate
etc.The code above assumes that the Allocator is the
std::pmr::polymorphic_allocator
which is correct (for this case) but it doesn't take into account thememory_resource
. That being said, the following assertions trigger:Which is different from the standard behavior (you can verify this by replacing
jsoncons::pmr::json
withstd::vector
and the assertion should pass.I am happy to contribute and take care of those two cases but I think it would be nice if we can somehow track all of those and fix them.
This is something that we need to properly track memory usage in our system.
Best regards.
The text was updated successfully, but these errors were encountered: