自定义的分配与承诺,并打包任务 [英] Custom allocators vs. promises and packaged tasks

查看:220
本文介绍了自定义的分配与承诺,并打包任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是标准的分配器回吐构造 / packaged_task 应该使用分配器只是状态对象本身,还是这应该保证的所有的(内部)相关的对象?

Are the allocator-taking constructors of standard promise/packaged_task supposed to use the allocator for just the state object itself, or should this be guaranteed for all (internal) related objects?

[futures.promise]:......分配内存共享状态结果
  [futures.task.members]:......需要分配存储内部数据结构存储

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

在特定的,是下面的错误或功能?

In particular, are the below bugs or features?

* MSVC 2013.4,提升1.57,霍华德Hinnant(欣南特) short_alloc.h

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

示例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;

}

输出:

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

FWIW,默认分配器输出

FWIW, the output with the default allocator is

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

例2

AFAICT,MSVC的的std ::互斥做一个不可避免的堆分配,因此,也是如此的std ::承诺它使用它。这是一个符合标准的行为?

AFAICT, MSVC's std::mutex does an unavoidable heap allocation, and therefore, so does std::promise which uses it. Is this a conformant behaviour?

推荐答案

N.B。有您的code几个问题。在C ++ 14如果更换的operator delete(void *的)则必须同时更换的operator delete(void *的,性病::尺寸)t )。您可以使用一个功能测试宏,看看如果编译器要求:

N.B. there are a couple of issues with your code. In C++14 if you replace operator delete(void*) then you must also replace operator delete(void*, std::size)t). You can use a feature-test macro to see if the compiler requires that:

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

其次为为size_t 正确的printf的格式说明不是 U ,所以你应该使用%伊豆

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

AFAICT,MSVC的的std ::互斥做一个不可避免的堆分配,因此,也是如此的std ::承诺它使用它。这是一个符合标准的行为?

AFAICT, MSVC's std::mutex does an unavoidable heap allocation, and therefore, so does std::promise which uses it. Is this a conformant behaviour?

这当然是值得商榷的std ::互斥是否应该使用动态分配。它的构造不能,因为它必须是 constexpr 。它可以延迟分配,直到第一次调用锁() try_lock(),但锁定()未列出未能获取资源为有效错误情况,这意味着 try_lock()可能无法锁定一个非竞争的互斥如果它不能分配其所需的资源。这是允许的,如果你眯着眼睛看着它,但效果不理想。

It's certainly questionable whether std::mutex should use dynamic allocation. Its constructor can't, because it must be constexpr. It could delay the allocation until the first call to lock() or try_lock() but lock() doesn't list failure to acquire resources as a valid error condition, and it means try_lock() could fail to lock an uncontended mutex if it can't allocate the resources it needs. That's allowed, if you squint at it, but is not ideal.

但对于你的主要问题,正如你所援引的标准只说这对

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

第二个构造函数使用分配器 A 为共享状态分配内存。

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

这并不是说有关的其他的受许所需的资源什么。这是合理的假设,像互斥的同步对象是共享的状态,而不是承诺的一部分,但这一措辞并不要求分配器用于共享状态的成员需要记忆,只为通过共享状态所需的内存本身。

That doesn't say anything about other resources needed by the promise. It's reasonable to assume that any synchronization objects like mutexes are part of the shared state, not the promise, but that wording doesn't require that the allocator is used for memory the shared state's members require, only for the memory needed by the shared state itself.

有关 packaged_task 措辞更广泛,意味着所有的内部状态应该使用分配器,但它可以说,这意味着分配器用于获取内存的存储任务和共享状态,但再次,该共享状态的成员不具有使用分配器。

For packaged_task the wording is broader and implies that all internal state should use the allocator, although it could be argued that it means the allocator is used to obtain memory for the stored task and the shared state, but again that members of the shared state don't have to use the allocator.

总之,我不认为这个标准是100%清楚MSVC实现是否是允许的,但恕我直言,这并不从的malloc需要额外的内存实施更好(这是如何的libstdc ++ &LT;未来&GT; 实施工作)。

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

这篇关于自定义的分配与承诺,并打包任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆