自定义分配器与承诺和打包任务

2024-04-20

标准的分配器构造函数是promise/packaged_task应该仅将分配器用于状态对象本身,或者应该保证这一点all(内部)相关对象?

[futures.promise]:“...为共享状态分配内存”
[futures.task.members]:“...分配存储内部数据结构所需的内存”

特别是以下是错误或功能吗?

*MSVC 2013.4,提升 1.57,Short_alloc.h 作者:Howard Hinnant http://howardhinnant.github.io/short_alloc.h

实施例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,默认分配器的输出是

...
[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、MSVCstd::mutex进行不可避免的堆分配,因此,std::promise它使用它。这是一致的行为吗?


注意:您的代码有几个问题。在 C++14 中,如果替换operator delete(void*)那么你还必须更换operator delete(void*, std::size)t)。您可以使用功能测试宏来查看编译器是否需要:

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

其次正确的 printf 格式说明符size_t is zu not u,所以你应该使用%Izu.

AFAICT、MSVCstd::mutex进行不可避免的堆分配,因此,std::promise它使用它。这是一致的行为吗?

这当然值得怀疑std::mutex应该使用动态分配。它的构造函数不能,因为它必须是constexpr。它可能会延迟分配,直到第一次调用lock() or try_lock() but lock()没有将获取资源失败列为有效错误条件,这意味着try_lock()如果无法分配所需的资源,则可能无法锁定无竞争的互斥体。如果你眯着眼睛看的话,这是允许的,但并不理想。

但关于您的主要问题,正如您引用的那样,该标准仅说明了这一点promise:

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

这并没有说明什么other承诺所需的资源。可以合理地假设任何同步对象(如互斥体)都是共享状态的一部分,而不是承诺,但这种措辞并不要求分配器用于共享状态的成员所需的内存,仅用于共享状态所需的内存本身。

For packaged_task该措辞更广泛,意味着所有内部状态都应该使用分配器,尽管可能有人认为这意味着分配器用于为存储的任务和共享状态获取内存,但同样,共享状态的成员不这样做必须使用分配器。

总之,我认为标准并不是 100% 清楚是否允许 MSVC 实现,但恕我直言,这是一个不需要额外内存的实现malloc or new更好(这就是 libstdc++ 的方式<future>实施工作)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义分配器与承诺和打包任务 的相关文章

随机推荐