c++memoryallocatorc++pmr

call allocate() again on the released unsynchronized_pool_resource is an undefined behavior or not?


I am currently leaning the behavior of unsynchronized_pool_resource. So I have this sample code

std::pmr::monotonic_buffer_resource buffer_resource{std::pmr::new_delete_resource()}; //monotonic wrapper raw memory get from new_delete_resource
std::pmr::unsynchronized_pool_resource   midlevel{&buffer_resource}; //2nd pool
std::pmr::unsynchronized_pool_resource   un_sync{&midlevel}; //3rd pool
std::pmr::polymorphic_allocator<MyClass> allocator{&un_sync}; //allocator get memory from 3rd pool

MyClass* t = allocator.allocate(1);
allocator.construct(t, 20);
allocator.destroy(t);

un_sync.release(); //release

MyClass* ttt = allocator.allocate(1); //call allocate on released memory resources 
allocator.construct(ttt, 40);
allocator.destroy(ttt);

It works fine, and after my test, it seems like the 3rd pool re-build the pool from the 2nd pool. I didn't find any explicit(or I didn't see) information about this behavior. So call allocate() again on the released unsynchronized_pool_resource is an undefined behavior or not?


Solution

  • As far as i can tell this should be fine.

    When you do:

    un_sync.release();
    

    This release function de-allocates all the memory, it doesn't drop the upstream resource's pointer. According to here:

    Releases all memory owned by this resource by calling the deallocate function of the upstream memory resource as needed.

    Memory is released back to the upstream resource even if deallocate has not been called for some of the allocated blocks.

    So this releases all the memory. But by calling de-allocate of the upstream resource. So when you do:

    MyClass* ttt = allocator.allocate(1); //call allocate on released memory resources 
    

    It is the same as the first time, you are calling allocate on the existing upstream.