0

由 Windows 支持的名为共享内存的 std::allocator(基于MAllocator )的实现向 MAllocator 添加了几个项目。

  • allocate()的附加参数名称改变了 std::allocator 上的签名。这可以,考虑到分配器通常是模板参数(错误将在编译时被捕获)?

    template<class T> T *allocate(const size_t n, const char* name);

  • 状态以指向 deallocate() 句柄的指针映射的形式维护。分配器拒绝与其他实例相等以保持状态完整性。这是否足够或是否需要额外的保障措施?

    typedef std::map<uintptr_t, HANDLE> HandleMap;
    HandleMap mHandles;
    
    deallocate(T *const p, size_t n = 0) 
    {
        if (mHandles.find((uintptr_t)p) == mHandles.end())  //we don't own this pointer
        {
            std::ostringstream msg;
            msg << "Error in deallocate(): Invalid pointer - we don't own it - we can't delete it!";
            throw std::exception(msg.str().c_str() );
        }
    
        unmapView(p);
        closeHandle(p);
        mHandles.erase((uintptr_t)p);
    }
    

github上的完整代码

4

1 回答 1

1

首先,您的问题是“对于 std::allocator”,但这不是 a std::allocator,而是 a ShmAllocatorstd::allocator是标准库提供的类模板,你的分配器不是那个类模板,它是不同的类型。我认为您的意思是“用于分配器”或仅用于“用于标准分配器”,它指的是符合分配器要求的类型(std::allocator只是这种类型的一个示例。)

这不符合分配器的要求,特别是副本不等于原始对象。如果您计划将此分配器与需要符合标准的分配器的代码一起使用,它可能会失败。如果您不打算将它与需要标准分配器的代码一起使用,那么为什么还要复制它的接口呢?

复制构造函数的要求要求,对于a类型对象,ShmAllocator<T>语句ShmAllocator<T> a1(a);有效,后置条件为 ,对于类型a1 == a对象,语句有效,后置条件为and 。bShmAllocator<U>ShmAllocator<T> a(b);ShmAllocator<U>(a) == ba == ShmAllocator<T>(b)

这些要求是必要的,因为容器需要能够重新绑定分配器并制作必须能够释放彼此内存的副本。有状态分配器的平等应该取决于价值而不是身份。

为了使您的分配器满足您可以存储的要求mHandlesshared_ptr<mHandles>以便分配器的副本可以共享同一个集合。

你打算如何使用这个分配器?我不知道 Windows API 函数,但似乎每次调用allocate时都需要使用不同的值,name否则会返回相同的指针,这意味着标准容器不能使用它。我希望共享内存分配器在其构造函数中创建一个共享内存区域(或通过对某些现有区域的引用来构造,例如参见 Boost.Interprocess 分配器)然后将该区域划分并返回它的不同块每次allocate被调用,而不是在每次调用时创建一个新区域allocate。这是为了让用户在进程之间共享对象吗?另一个进程如何访问现有对象?似乎另一个进程必须调用allocate获取指向已构造对象的指针。这很令人困惑,allocate应该提供新的、未初始化的内存。共享内存分配器通常会定义一个自定义指针类型,它将偏移存储到共享内存区域而不是绝对地址,因此当这样的指针用于不同的进程时,偏移仍然有效,即使该区域是映射到不同的地址。

于 2012-06-17T19:18:57.433 回答