Advertisement
Guest User

Untitled

a guest
Dec 15th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.39 KB | None | 0 0
  1. #include "turnstile.h"
  2. #include <vector>
  3. #include <cassert>
  4. #include <iostream>
  5. #include <queue>
  6.  
  7. namespace {
  8.     Turnstile* const dummy = new Turnstile();
  9.  
  10. class TurnstilePool {
  11. private:
  12.     std::mutex m;
  13.     std::vector<Turnstile*> pool;
  14.     int size;
  15.  
  16.     void extendPool() {
  17.         size *= 2;
  18.         for (int i = 1; i <= size; ++i)
  19.             pool.push_back(new Turnstile());
  20.     }
  21.  
  22. public:
  23.     TurnstilePool() :
  24.             size(2) {
  25.         for (int i = 1; i <= size; ++i)
  26.             pool.push_back(new Turnstile());
  27.     }
  28.  
  29.     ~TurnstilePool() {
  30.         while (!pool.empty()) {
  31.             Turnstile *remove = pool.back();
  32.             pool.pop_back();
  33.             delete remove;
  34.         }
  35.         delete dummy;
  36.     }
  37.  
  38.     Turnstile *getTurnstile() {
  39.         std::lock_guard<std::mutex> lk(m);
  40.  
  41.         if (pool.empty())
  42.             extendPool();
  43.  
  44.         Turnstile *ret = pool.back();
  45.         pool.pop_back();
  46.  
  47.         return ret;
  48.     }
  49.  
  50.     void returnToPool(Turnstile *turnstile) {
  51.         std::lock_guard<std::mutex> lk(m);
  52.  
  53.         pool.push_back(turnstile);
  54.         if (size > 2 && (int)pool.size() * 2 >= size * 3) {
  55.             for (int i = 1; i <= size / 2; ++i) {
  56.                 Turnstile *remove = pool.back();
  57.                 pool.pop_back();
  58.                 delete remove;
  59.             }
  60.  
  61.             size /= 2;
  62.         }
  63.     }
  64. };
  65.  
  66. TurnstilePool& pool() {
  67.     static TurnstilePool pool;
  68.     return pool;
  69. }
  70.  
  71. inline std::mutex& getInternalMutex(Mutex *ptr) {
  72.     static const int MUTEX_NO = 307;
  73.     static std::mutex internalMutexes[MUTEX_NO];
  74.  
  75.     return internalMutexes[((long long)((long long)ptr % MUTEX_NO) * 97LL) % MUTEX_NO];
  76. }
  77.  
  78. }
  79.  
  80. Turnstile::Turnstile() :
  81.             waitingNo(0), secure(false) {
  82.         m = new std::mutex;
  83. }
  84.  
  85. Turnstile::~Turnstile() {
  86.     delete m;
  87. }
  88.  
  89. Mutex::Mutex() {
  90.     ptr = nullptr;
  91. }
  92.  
  93. void Mutex::lock() {
  94.     getInternalMutex(this).lock();
  95.  
  96.     if (ptr == nullptr)
  97.         ptr = dummy;
  98.     else {
  99.         if (ptr == dummy)
  100.             ptr = pool().getTurnstile();
  101.  
  102.         ptr->waitingNo++;
  103.         getInternalMutex(this).unlock();
  104.        
  105.         std::unique_lock<std::mutex> lk(*(ptr->m));
  106.         ptr->cv.wait(lk, [this] { return ptr->secure; });
  107.  
  108.         getInternalMutex(this).lock();
  109.         ptr->secure = false;
  110.         ptr->waitingNo--;
  111.  
  112.         if (ptr->waitingNo == 0) {
  113.             pool().returnToPool(ptr);
  114.             ptr = dummy;
  115.         }
  116.     }
  117.  
  118.     getInternalMutex(this).unlock();
  119. }
  120.  
  121. void Mutex::unlock() {
  122.     getInternalMutex(this).lock();
  123.  
  124.     if (ptr == dummy)
  125.         ptr = nullptr;
  126.     else {
  127.         assert(ptr->waitingNo);
  128.         std::lock_guard<std::mutex> lk(*(ptr->m));
  129.         ptr->secure = true;
  130.         ptr->cv.notify_one();
  131.     }
  132.  
  133.     getInternalMutex(this).unlock();
  134. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement