shared pipe hlxSweExam

#include <cstdlib>
#include <new>
template <class T>
struct Mallocator {
  typedef T value_type;
  Mallocator() = default;
  template <class U> constexpr Mallocator(const Mallocator<U>&) noexcept {}
  [[nodiscard]] T* allocate(std::size_t n) {
    if(n > std::size_t(-1) / sizeof(T)) throw std::bad_alloc();
    if(auto p = static_cast<T*>(std::malloc(n*sizeof(T)))) return p;
    throw std::bad_alloc();
  }
  void deallocate(T* p, std::size_t) noexcept { std::free(p); }
};
template <class T, class U>
bool operator==(const Mallocator<T>&, const Mallocator<U>&) { return true; }
template <class T, class U>
bool operator!=(const Mallocator<T>&, const Mallocator<U>&) { return false; }

https://elloop.github.io/c++/2016-09-19/stl-apply-imp-95-simple-allocator


http://www.cnblogs.com/suzhou/p/5381738.html

http://www.justskins.com/forums/shm_open-vs-open-253314.html

http://www.drdobbs.com/creating-stl-containers-in-shared-memory/184401639 

http://people.cs.aau.dk/~adavid/teaching/MTP-05/lectures/13/Inter-Process_Communication.pdf

https://stackoverflow.com/questions/10518820/how-can-i-use-operators-new-and-delete-within-shared-memory

https://pdfs.semanticscholar.org/7b55/610961c63b86141f37c68e73e0326fae0693.pdf 


https://accu.org/content/conf2013/Frank_Birbacher_Allocators.r210article.pdf

https://zh.wikipedia.org/wiki/%E5%88%86%E9%85%8D%E5%99%A8_(C%2B%2B) 






http://en.cppreference.com/w/cpp/concept/Allocator

  • A::pointer 指针
  • A::const_pointer 常量指针
  • A::reference 引用
  • A::const_reference 常量引用
  • A::value_type 值类型
  • A::size_type 所用内存大小的类型,表示类A所定义的分配模型中的单个对象最大尺寸的无符号整型
  • A::difference_type 指针差值的类型,为带符号整型,用于表示分配模型内的两个指针的差异值[文 3] 
  • 定义自定义分配器的主要原因之一是提升性能。利用专用的自定义分配器可以提高程序的效能,又或提高内存使用效率,亦或两者兼而有之[4][8]。默认分配器使用new操作符分配存储空间[文 5],而这常利用C语言堆分配函数(malloc())实现[9]。由于堆分配函数常针对偶发的内存大量分配作优化,因此在为需要一次分配大量内存的容器(如向量双端队列)分配内存时,默认分配器一般效率良好[8]。但是,对于关联容器双向链表这类需要频繁分配少量内存的容器来说,若采用默认分配器分配内存,则通常效率很低[4][9]。除此之外,基于malloc()的默认分配器还存在许多问题,诸如较差的引用局部性[4],以及可能造成内存碎片化[4][9]
    简言之,此段(……)(如同)是这一标准针对分配器的一场《我有一个梦想》的演讲。在梦想成真之前,关心可移植性的程序员将把自己局限于(使用)无状态的自定义分配器上。
    ——斯科特 梅耶斯,《Effective STL》
    有鉴于此,在这一情况下,人们常使用基于内存池的分配器来解决频繁少量分配问题[8]。与默认的“按需分配”方式不同,在使用基于内存池的分配器时,序会预先为之分配大块内存(即“内存池”),而后在需要分配内存时,自定义分配器只需向请求方返回一个指向池内内存的指针即可;而在对象析构时,并不需实际解除分配内存,而是延迟到内存池的生命周期完结时才真正解除分配[註 1][8]
    在“自定义分配器”这一话题上,已有诸多C++专家与相关作者参与探讨,例如斯科特·梅耶斯的作品《Effective STL》与安德烈·亚历山德雷斯库的《Modern C++ Design》都有提及。梅耶斯洞察到,若要求针对某一类型T的分配器的所有实例都相等,则可移植的分配器的实例必须不包含状态。虽然C++标准鼓励库的实现者支持带状态的分配器[文 4],但梅耶斯称,相关段落是“(看似)美妙的观点”,但也几乎是空话,并称分配器的限制“过于严苛”[4]。例如,STL的list允许splice方法,即一个list对象A的节点可以被直接移入另一个list对象B中,这就要求A的分配器申请到的内存,可被B的分配器释放掉,从而推导出A与B的分配器实例必须相等。梅耶斯的结论是,分配器最好定义为使用静态方法的类型。例如,根据C++标准,分配器必须提供一个实现了rebind方法的other类模板。
    另外,在《C++程序设计语言》中,比雅尼·斯特劳斯特鲁普则认为“‘严格限制分配器,以免各对象信息不同’,这点显然问题不大”(大意),并指出大部分分配器并不需要状态,甚至没有状态情形下性能反倒更佳。他提出了三个自定义分配器的用例:内存池型的分配器、共享内存型分配器与垃圾回收型分配器,并展示了一个分配器的实现,此间利用了一个内部内存池,以快速分配/解除分配少量内存。但他也提到,如此优化可能已经在他所提供的样例分配器中实现[3]
    自定义分配器的另一用途是调试内存相关错误[10]。若要做到这一点,可以编写一个分配器,令之在分配时分配额外的内存,并借此存放调试信息。这类分配器不仅可以保证内存由同类分配器分配/解除分配内存,还可在一定程度上保护程序免受缓存溢出之害[11]
     

留言

這個網誌中的熱門文章

https://leetcode.com/contest/leetcode-weekly-contest-52/problems/longest-univalue-path/

https://leetcode.com/contest/leetcode-weekly-contest-52/problems/maximum-sum-of-3-non-overlapping-subarrays/