visual-c++ - 自定义分配器与 promise 和打包任务

标签 visual-c++ c++11 boost language-lawyer c++14

是标准 promise 的分配器构造函数吗?/packaged_task应该仅将分配器用于状态对象本身,还是应该保证所有(内部)相关对象都可以使用分配器?

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



特别是以下错误或功能?

*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,默认分配器的输出是
...
[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::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

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

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

但是关于您的主要问题,正如您所引用的,标准仅针对 promise 说明了这一点。 :

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



这并没有说明 promise 所需的其他资源。可以合理地假设任何像互斥锁这样的同步对象都是共享状态的一部分,而不是 promise ,但该措辞不要求分配器用于共享状态成员所需的内存,仅用于共享状态所需的内存本身。

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

总之,我认为标准是否 100% 明确是否允许 MSVC 实现,但恕我直言,一个不需要来自 malloc 的额外内存的实现。或 new更好(这就是 libstdc++ <future> 实现的工作原理)。

关于visual-c++ - 自定义分配器与 promise 和打包任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28069443/

相关文章:

visual-c++ - Visual C++ 11 在 CMake 生成的项目中找不到 Boost unit_test_framework 库

c++ - 如何将类方法的地址转换为 (void *)

c++ - 如何解释 C++ 语法中的 decl-specifier

c++ - 您可以将指针转换为数组吗?

c++ - 从源代码构建 Qt 5.8 - 配置 : Unknown command line option '-c++11'

c++ - 如何将字符插入集合?

C# BlockingCollection 的 c++/boost 模拟?

c - Loadlibrary 总是返回 NULL

c++ - Boost Python 和 shared_ptr 向上转换

c++ - 为什么我必须为每个 namespace 定义一个哈希函数作为 unordered_set?