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