上下文:我正在编写一个库,它为许多stdlib数据结构中的自定义分配器公开,以便为想要自定义内存分配以实现实时性能的用户提供。
我想使用std::promise
和std::future
的自定义分配器。我的理解是,当一个分配器传递给std::promise
时,它的future
对象也会使用该自定义分配器。
我的测试会覆盖全局new和delete以跟踪调用默认运算符的次数。我还实现了一个使用malloc
和free
的自定义分配器,但使用不同的状态来计算分配/解除分配(在实际示例中,它将替换为实时安全分配器)。
当我打电话给std::promise::set_value
来表示"大"对象,全局运算符new和delete被调用,即使promise
是使用自定义分配器构造的。
这是一个基本的例子。 (为简洁起见,删除了分配器样板,您可以在Gist上看到完整的,可编译的版本:https://gist.github.com/jacquelinekay/a4a1a282108a55d545a9)
struct Foo {
std::vector<int, InstrumentedAllocator<int>> bar;
};
int main(int argc, char ** argv) {
(void) argc;
(void) argv;
InstrumentedAllocator<void> alloc;
std::promise<Foo> promise_(std::allocator_arg, alloc);
std::shared_future<Foo> future_ = promise_.get_future().share();
// Start a thread that blocks for a few ms and sets the future value
std::thread result_thread(
[&promise_]() {
Foo result;
result.bar.push_back(1);
result.bar.push_back(2);
result.bar.push_back(3);
// test_init starts counting calls to global new/delete
// (stored in variables global_runtime_allocs/deallocs)
test_init = true;
std::this_thread::sleep_for(std::chrono::milliseconds(5));
promise_.set_value(result);
test_init = false;
}
);
future_.wait();
result_thread.join();
std::cout << "Runtime global allocations: " << global_runtime_allocs << " (expected: 0)" << std::endl;
std::cout << "Runtime global deallocations: " << global_runtime_deallocs << " (expected: 0)" << std::endl;
}
此示例的全局运算符new也会打印&#34;运行时&#34;的大小。分配(来自std::promise::set_value
),产生此输出:
$ clang++ promise_allocator.cpp -std=c++11 -lpthread
$ ./a.out
Allocation size: 16
Runtime global allocations: 1 (expected: 0)
Runtime global deallocations: 1 (expected: 0)
我在gcc 4.8和Clang 3.4上得到了相同的结果。这是对标准的正确解释吗?我希望set_value
能够使用promise
的分配器。
答案 0 :(得分:1)
结合使用调试器回溯并结合GCC的stdlib实现,我已经找到为什么会发生这种情况,尽管我自己没有解决方案或解决方法。
std::promise::set_value
调用其未来的内部函数future::_M_set_result
。 [1]将函数对象__res
传递给此函数会调用_Function_base
的构造函数,可能是因为函数的签名未通过引用传递__res_
。 [2] _Function_base
的构造函数调用_M_init_functor
,如果函数使用本地存储或分配新对象,则执行新的放置。 [3]由于某些原因我还没有确定,future
内部使用的函数不使用本地存储,因此在构造函数中分配。
从略读我能找到的标准的工作草案[4],该标准并未具体说明promise
中预期的分配行为。但是,我不能控制promise
内部使用的函数的分配行为是不方便的,我可能会在gcc中提出一个关于它的错误。
答案 1 :(得分:1)
这似乎是4.9版本系列libstdc ++中的一个错误,该错误在版本5发行版系列中得到修复。使用version 5.1或更高版本在Wandbox上运行您的要点仅产生输出:
Runtime global allocations: 0 (expected: 0) Runtime global deallocations: 0 (expected: 0)