2245. packaged_task::reset() memory allocation

Section: 33.6.10.1 [futures.task.members] Status: Resolved Submitter: Jonathan Wakely Opened: 2013-03-05 Last modified: 2017-03-20

Priority: 3

View all other issues in [futures.task.members].

View all issues with Resolved status.

Discussion:

The effects of packaged_task::reset() result in memory allocation, but don't allow a user to provide an allocator.

packaged_task::reset() needs to be overloaded like so:

template<class Alloc>  
void reset(const Alloc&);

Alternatively, the effects of reset() need to require the same allocator is used as at construction, which would require the constructor to store the allocator for later use.

I like to remark that GCC at the moment uses the second option, i.e. the allocator passed to the constructor (if any) is used to create the new shared state, because this didn't require any change to the interface.

[2015-02 Cologne]

Handed over to SG1.

[2015-05 Lenexa, SG1 response]

No strong opinions in SG1, and this is really an LWG issue. Back to you.

[2016-08-02 Chicago, Billy O'Neal comments and suggests concrete wording]

Talked this over with Alasdair, who says there's little desire to allow the packaged_task to be change allocators after initial construction, making what libstdc++ does already the "right thing." A clarification note is still necessary to indicate that the allocator supplied to the allocator_arg_t constructor is to be used.

Wed PM: Move to Tentatively Ready

[2016-09-08]

Alisdair requests change to Review.

[2017-03-03, Kona]

This was resolved by adopting 2921, which removed the constructors that take allocators.

Proposed resolution:

This wording is relative to N4606

  1. Change 33.6.10.1 [futures.task.members] as indicated:

    void reset();
    

    -22- Effects:

    • if the shared state associated with *this was created via the packaged_task(F&& f) constructor, aAs if *this = packaged_task(std::move(f)), where f is the task stored in *this.

    • if the shared state associated with *this was created via the packaged_task(allocator_arg_t, Allocator& a, F&&) constructor, as if *this = packaged_task(allocator_arg, a, std::move(f)), where a is the allocator used to allocate the shared state associated with *this, and f is the task stored in *this.

    [Note: This constructs a new shared state for *this. The old state is abandoned (30.6.4). — end note]

    -23- Throws:

    • if no allocator was used, bad_alloc if memory for the new shared state could not be allocated.

    • if an allocator was used, any exception thrown by std::allocator_traits<Allocator>::template rebind_traits<unspecified>::allocate.

    • any exception thrown by the move constructor of the task stored in the shared state.

    • future_error with an error condition of no_state if *this has no shared state.