许多异步操作需要分配一个对象来存储与操作关联的状态。例如,Win32 实现需要 OVERLAPPED-derived 对象传递给 Win32 API 函数。
此外,程序通常包含易于识别的异步操作链。半双工协议实现(例如 HTTP 服务器)每个客户端具有单个操作链(接收后发送)。全双工协议实现将有两个并行执行的链。程序应该能够利用这些知识为链中的所有异步操作重用内存。
给定一个用户定义Handler 对象 h 的副本,如果实现需要分配与该handler关联的内存,它将使用 get_associated_allocator 函数获得一个分配器。例如:
asio::associated_allocator_t<Handler> a = asio::get_associated_allocator(h);
关联的分配器必须满足标准的 Allocator 要求。
默认情况下,处理程序使用标准Allocator(根据::operator new() 和 ::operator delete() 实现)。 通过指定嵌套类型allocator_type和成员函数get_allocator(),可以为特定的handler类型定制分配器.
class my_handler
{
public:
// Custom implementation of Allocator type requirements.
typedef my_allocator allocator_type;
// Return a custom allocator implementation.
allocator_type get_allocator() const noexcept
{
return my_allocator();
}
void operator()() { ... }
};
在更复杂的情况下,associated_allocator 模板可以直接偏特化:
namespace asio {
template <typename Allocator>
struct associated_allocator<my_handler, Allocator>
{
// Custom implementation of Allocator type requirements.
typedef my_allocator type;
// Return a custom allocator implementation.
static type get(const my_handler&,
const Allocator& a = Allocator()) noexcept
{
return my_allocator();
}
};
} // namespace asio
该实现保证释放将在调用关联的handler之前发生,这意味着内存已准备好被handler启动的任何新异步操作重用。
可以从正在调用库函数的任何用户创建的线程调用自定义内存分配函数。该实现保证,对于包含库的异步操作,该实现不会对该handler的内存分配函数进行并发调用。如果需要从不同线程调用分配函数,该实现将插入适当的内存屏障以确保正确的内存可见性。