Skip to content
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

Support construction with allocators for allocator-aware types #24

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

justusranvier
Copy link
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
Copy link
Member

agserm commented Jan 18, 2024

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
Copy link
Contributor Author

justusranvier commented Jan 18, 2024

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
Copy link
Contributor Author

justusranvier commented Jan 18, 2024

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
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