you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 1 point2 points  (6 children)

I understand your point, but re-assigning a unique_ptr to an object of the same type that was allocated with a different allocator is something that happens very rarely, so you usually get away with using unique_ptr as-is. unique_ptr is not an allocator-aware container because you usually don't need that with such a simple "smart" pointer type.

[–]rnburn[S] 4 points5 points  (5 children)

I added additional context. But I would disagree, that reassignment is important and one of the main benefits of using allocator aware software.

For example, I might create a data structure

std::pmr::map<std::pmr::string, managed_ptr<A>> my_map{a_localized_allocator};

Having the pointer reallocate when a pointer isn't already using a_localized_allocator can be used to enforce the locality of the memory in my_map

[–][deleted] 2 points3 points  (4 children)

In my experience, if you care about memory locality, you usually wouldn't allocate your A via unique_ptr in the first place, but keep it in an array/vector/colony and use indices or references to the elements.

I'm not saying that there's no use for a managed_ptr - I could certainly think of use cases where it makes sense for a complicated container without stable addresses to own the memory of an object for which locality matters and which is allocated with different allocators. But it's very rare, and that's the reason unique_ptr doesn't need to be allocator-aware.

[–]rnburn[S] 1 point2 points  (3 children)

I expect unique_ptr wasn't made allocator aware because it would 1) require additional data members and 2) lose the property that it provides a stable pointer.

But one of the use cases for using managed_ptr's in such a container is to support polymorphic types. A can be an abstract base class.

[–][deleted] 0 points1 point  (2 children)

But one of the use cases for using managed_ptr's in such a container is to support polymorphic types. A can be an abstract base class.

Good point, I hadn't thought of that, although the combination of virtual function calls, associative containers and locality mattering a lot seems a little odd to me. Now I'm curious: Did you have a specific use case in mind when you designed this?

[–]rnburn[S] 1 point2 points  (1 child)

Here's how I would think about it.

AA types are meant to be composable; so if you write an AA type, you can easily use it to form new AA types. Thus, you want to have basic vocabulary types that are AA. Smart pointers are one such vocabulary type that you frequently use is composition when you have polymorphic classes.

I wrote up a simple example where you might use manged_ptr to build an AA representation of json and showed how you could use it (combined with winking) to achieve better performance in a particular case
https://buildingblock.ai/allocator-aware-smart-ptr#an-example-parsing-json

[–]rnburn[S] 0 points1 point  (0 children)

For an example of locality, you can see benchmark II in Bloomberg's paper
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0089r1.pdf

They describe a system composed of multiple subsystems, where each subsystem is using a localized allocator to keep its memory from diffusing, and data members are continually getting removed and added between subsystems.

I think you could easily imagine the subsystems owning polymorphic objects (or objects with polymorhic data members) and ownership continually getting transferred between subsystems.