Custom dispensers versus promises and packaged tasks

Are the default promise / packaged_task use a allocator only for the state object itself, or should it be guaranteed for all (internal) related objects?

[futures.promise]: "... allocate memory for general state"
[futures.task.members]: "... allocate the memory needed to store internal data structures"

In particular, are these the following errors or functions?

* MSVC 2013.4, Boost 1.57, short_alloc.h from Howard Hinnant

Example 1

 #define BOOST_THREAD_VERSION 4 #include <boost/thread/future.hpp> #include "short_alloc.h" #include <cstdio> void *operator new( std::size_t s ) { printf( "alloc %Iu\n", s ); return malloc( s ); } void operator delete( void *p ) { free( p ); } int main() { const int N = 1024; arena< N > a; short_alloc< int, N > al( a ); printf( "[promise]\n" ); auto p = boost::promise< int >( std::allocator_arg, al ); p.set_value( 123 ); printf( "[packaged_task]\n" ); auto q = boost::packaged_task< int() >( std::allocator_arg, al, [] { return 123; } ); q(); return 0; } 

Output:

 ... [promise] alloc 8 alloc 12 alloc 8 alloc 24 [packaged_task] alloc 8 alloc 12 alloc 8 alloc 24 

FWIW, default output with dispenser -

 ... [promise] alloc 144 alloc 8 alloc 12 alloc 8 alloc 16 [packaged_task] alloc 160 alloc 8 alloc 12 alloc 8 alloc 16 

Example 2

AFAICT, MSVC std::mutex does the inevitable heap allocation, so std::promise is used, which uses it. Is this behavior consistent?

+7
language-lawyer boost c ++ 11 visual-c ++ c ++ 14
source share
1 answer

NB there are a couple of problems with your code. In C ++ 14, if you replace operator delete(void*) , you must also replace operator delete(void*, std::size)t) . You can use the function test macro to find out if the compiler requires:

 void operator delete( void *p ) { free( p ); } #if __cpp_sized_deallocation // Also define sized-deallocation function: void operator delete( void *p, std::size_t ) { free( p ); } #endif 

Secondly, the correct printf format specifier for size_t is zu not u , so you should use %Izu .

AFAICT, MSVC std::mutex makes the inevitable allocation of the heap, and therefore uses std::promise , which uses it. Is this behavior consistent?

Of course, it is doubtful whether std::mutex should use dynamic allocation. Its constructor cannot, since it must be constexpr . This may delay allocation until the first call to lock() or try_lock() , but lock() does not report a resource retrieval error as a valid error condition, which means that try_lock() may not block the messy mutex if it cannot allocate the resources he needs. This allowed if you squinted, but not perfect.

But regarding your main question, as you quoted, the standard only talks about this for promise :

The second constructor uses allocator a to allocate memory for general state.

This does not say anything about other resources needed for a promise. It is reasonable to assume that any synchronization objects, such as mutexes, are part of the general state, and not a promise, but this formulation does not require the allocator to be used for memory, which requires common state members, only for the memory necessary for the general state in itself .

For packaged_task wording is broader and implies that the entire internal state must use the allocator, although it can be argued that this means that the allocator is used to obtain memory for the stored task and general state, but again that the general state members do not need to use the allocator.

In general, I don’t think that the standard is 100% clear whether the MSVC implementation is allowed, but IMHO does not better implement an implementation that does not need additional memory from malloc or new (and that how libstdC ++ <future> works.)

+1
source share

All Articles