Skip to content

Support construction with allocators for allocator-aware types - #24

Open
justusranvier wants to merge 1 commit into
copperspice:masterfrom
justusranvier:master
Open

justusranvier wants to merge 1 commit into
copperspice:masterfrom
justusranvier:master

Conversation

@justusranvier

Copy link
Copy Markdown
Contributor

Add a constructor and type trait specialization which is active if T is allocator-aware

This allows a std::shared_ptr for a guarded type to be constructed with std::allocate_shared.

Add a constructor and type trait specialization which is active if T is allocator-aware

This allows a std::shared_ptr for a guarded type to be constructed with std::allocate_shared.
@agserm

agserm commented Jan 18, 2024

Copy link
Copy Markdown
Member

Thanks for submitting this, it does look like a useful feature. However, I looked at this recently and started to add some unit tests for the new functionality, and realized that something seems strange with the implementation of the uses_allocator specialization.

Can you give an example of a T where the uses_allocator trait is expected to be true? It would be good to have a use case.

@justusranvier

justusranvier commented Jan 18, 2024

Copy link
Copy Markdown
Contributor Author

The complication is that there's two ways to get the uses_allocator trait: the leading-allocator convention and the trailing-allocator convention.

This PR only works with types that use leading-allocator convention, in other words if the first argument of the constructor is std::allocator_arg.

Somebody who is better at TMP than me could probably adapt it to also work with trailing-allocator convention, but all the types I want to guard are leading-allocator and supporting both conventions would likely be a much more intrusive change. You might need to add new template parameters to every class.

@justusranvier

justusranvier commented Jan 18, 2024

Copy link
Copy Markdown
Contributor Author

Here's an example of a leading-allocator convention type, showing how it can be constructed with or without allocator construction:

struct TestType {
    using allocator_type = std::pmr::polymorphic_allocator<>;

    std::pmr::string example;

    TestType(allocator_type alloc = {}, std::string_view value = {})
        : example(value, alloc)
    {
    }
    TestType(
        std::allocator_arg_t,
        allocator_type alloc,
        std::string_view value = {})
        : TestType(alloc, value)
    {
    }
};

auto resource = std::pmr::monotonic_buffer_resource{};
auto alloc = std::pmr::polymorphic_allocator<>{&resource};
std::ignore = std::allocate_shared<TestType>(alloc);
std::ignore = TestType{};

@justusranvier

Copy link
Copy Markdown
Contributor Author

The goal would be able to write

auto guarded_object = std::allocate_shared<libguarded::plain_guarded<TestTyoe>>{alloc};

And then pass the resulting std::shared_ptr to objects running in different threads.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants