Advertisement
Guest User

Untitled

a guest
May 20th, 2018
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.22 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <cstdlib>
  4. #include <sys/mman.h>
  5. #include <tpcc/lockfree/x86_64_atomic_stamped_pointer.hpp>
  6. #include <tpcc/thread/thread_local.hpp>
  7. #include <type_traits>
  8.  
  9. namespace tpcc {
  10.   namespace detail {
  11.     template <size_t kChunkSize, class=std::enable_if_t<(kChunkSize >= sizeof(void*))>>
  12.     class FixedSizeAllocator {
  13.      private:
  14.       struct Node {
  15.         std::atomic<Node*> next_;
  16.  
  17.       };
  18.  
  19.       struct Chunk {
  20.         void*& AsPointer() const {
  21.           return *static_cast<void**>(data_);
  22.         }
  23.  
  24.         Node* AsNode() const {
  25.           return static_cast<Node*>(static_cast<void*>(data_));
  26.         }
  27.  
  28.         uint8_t data_[kChunkSize];
  29.       };
  30.  
  31.       struct Arena {
  32.         static const size_t kChunksInArena = 1024;
  33.         static const size_t kArenaSize = kChunkSize * kChunksInArena;
  34.         Chunk chunks_[kChunksInArena];
  35.       };
  36.  
  37.       struct ArenaStack {
  38.         ArenaStack() {
  39.         }
  40.  
  41.         ~ArenaStack() {
  42.           while (lastArena_ != nullptr) {
  43.             Arena* nextArena = static_cast<Arena*>(lastArena_->chunks_[0].AsPointer());
  44.             munmap(lastArena_, Arena::kArenaSize);
  45.             lastArena_ = nextArena;
  46.           }
  47.         }
  48.  
  49.         Chunk* NewChunk() {
  50.           if (freeChunksInLastArena_ == 0) {
  51.             AllocateNewArena();
  52.           }
  53.           return &lastArena_->chunks_[freeChunksInLastArena_--];
  54.         }
  55.  
  56.         void AllocateNewArena() {
  57.           Arena* newArena = static_cast<Arena*>(mmap(NULL, Arena::kArenaSize, PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0));
  58.           newArena->chunks_[0].AsPointer() = static_cast<void*>(lastArena_);
  59.           lastArena_ = newArena;
  60.           freeChunksInLastArena_ = Arena::kChunksInArena - 1;
  61.         }
  62.  
  63.         size_t freeChunksInLastArena_{0};
  64.         Arena* lastArena_{nullptr};
  65.       };
  66.  
  67.       struct NodeStack {
  68.         using NodePtr = tpcc::lockfree::X86AtomicStampedPointer<Node>;
  69.  
  70.         NodeStack() {
  71.         }
  72.  
  73.         ~NodeStack() {
  74.         }
  75.  
  76.         void PushNode(Node* node) {
  77.           typename NodePtr::StampedPtr oldTop;
  78.           do {
  79.             oldTop = top_.Load();
  80.             node->next_.store(oldTop.raw_ptr_);
  81.           } while (!top_.CompareAndSet(oldTop, node));
  82.         }
  83.  
  84.         Node* PopNode() {
  85.           typename NodePtr::StampedPtr oldTop;
  86.           Node* newTop;
  87.           do {
  88.             oldTop = top_.Load();
  89.             if (!oldTop) {
  90.               return nullptr;
  91.             }
  92.             newTop = oldTop->next_.load();
  93.           } while (!top_.CompareAndSet(oldTop, newTop));
  94.           return oldTop.raw_ptr_;
  95.         }
  96.  
  97.         NodePtr top_{nullptr};
  98.       };
  99.  
  100.      public:
  101.       FixedSizeAllocator() {
  102.       }
  103.  
  104.       ~FixedSizeAllocator() {
  105.       }
  106.  
  107.       void* New() {
  108.         Node* node = pool_.PopNode();
  109.         if (node == nullptr) {
  110.           return arenaList_.Get().NewChunk();
  111.         } else {
  112.           return node;
  113.         }
  114.       }
  115.  
  116.       void Delete(void* ptr) {
  117.         Node* node = static_cast<Node*>(ptr);
  118.         pool_.PushNode(node);
  119.       }
  120.  
  121.      private:
  122.       NodeStack pool_;
  123.       tpcc::thread::ThreadLocal<ArenaStack> arenaList_;
  124.     };
  125.   } // namespace detail
  126. } // namespace tpcc
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement