Is std::pmr::set_default_resource unusable in multi-threaded programs?

238 views Asked by At

So, I finally had a reason to use polymorphic allocators.

Almost immediately, I discovered what appears to be a fatal design flaw: [mem.res.global]/3-7 doesn't state it outright, but the title of the section and remark about synchronization in [mem.res.global]/6 seem to imply std::pmr::get_default_resource and std::pmr::set_default_resource use a single static (i.e. not thread_local) default memory resource pointer.

Is my reading correct? If so, how is one expected to use polymorphic allocators in multi-threaded programs, considering that std::pmr::get_default_resource would implicitly be used all over the place when copying containers using them? Do I just have to always explicitly pass allocators around?

1

There are 1 answers

0
fatun On

I was wondering about the same question.

I wrote a simple test where two threads are changing/printing the default resource in order.

void task1 () {
    std::pmr::monotonic_buffer_resource pool;
    std::pmr::set_default_resource (&pool);
    std::cout << "task1 pool: " << std::pmr::get_default_resource () << std::endl;
    std::this_thread::sleep_for (std::chrono::milliseconds (1000));
    std::cout << "task1 pool: " << std::pmr::get_default_resource () << std::endl;
}

void task2 () {
    std::pmr::monotonic_buffer_resource pool;
    std::this_thread::sleep_for (std::chrono::milliseconds (500));
    std::pmr::set_default_resource (&pool);
    std::cout << "task2 pool: " << std::pmr::get_default_resource () << std::endl;
    std::this_thread::sleep_for (std::chrono::milliseconds (1000));
    std::cout << "task2 pool: " << std::pmr::get_default_resource () << std::endl;
}

It indicates default resource is global, not per thread.

https://coliru.stacked-crooked.com/a/6dbe796556712089

Results:

 task1 pool: 0x7fdcc1ee6ea0
 task2 pool: 0x7fdcc16e5ea0
 task1 pool: 0x7fdcc16e5ea0
 task2 pool: 0x7fdcc16e5ea0