shushus

Спринт 9. mutex и lock_guard.

Mar 6th, 2023
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.13 KB | None | 0 0
  1. #include <future>
  2. #include <mutex>
  3. #include <numeric>
  4. #include <queue>
  5. #include <string>
  6. #include <thread>
  7. #include <vector>
  8.  
  9. #include "test_framework.h"
  10.  
  11. using namespace std;
  12.  
  13. template <typename T>
  14. class Synchronized {
  15. public:
  16.     explicit Synchronized(T initial = T()) : value_(move(initial)) {};
  17.  
  18.     struct Access {
  19.         T& ref_to_value;
  20.         lock_guard<mutex> lock_guard_mutex;
  21.     };
  22.  
  23.     Access GetAccess() {
  24.         return {value_,
  25.                 lock_guard(mutex_)};
  26.     }
  27.  
  28. private:
  29.     T value_;
  30.     mutex mutex_;
  31. };
  32.  
  33. void TestConcurrentUpdate() {
  34.     Synchronized<string> common_string;
  35.  
  36.     const size_t add_count = 50000;
  37.     auto updater = [&common_string, add_count] {
  38.         for (size_t i = 0; i < add_count; ++i) {
  39.             auto access = common_string.GetAccess();
  40.             access.ref_to_value += 'a';
  41.         }
  42.     };
  43.  
  44.     auto f1 = async(updater);
  45.     auto f2 = async(updater);
  46.  
  47.     f1.get();
  48.     f2.get();
  49.  
  50.     ASSERT_EQUAL(common_string.GetAccess().ref_to_value.size(), 2 * add_count);
  51. }
  52.  
  53. vector<int> Consume(Synchronized<deque<int>>& common_queue) {
  54.     vector<int> got;
  55.  
  56.     for (;;) {
  57.         deque<int> q;
  58.  
  59.         {
  60.             auto access = common_queue.GetAccess();
  61.             q = move(access.ref_to_value);
  62.         }
  63.  
  64.         for (int item : q) {
  65.             if (item > 0) {
  66.                 got.push_back(item);
  67.             } else {
  68.                 return got;
  69.             }
  70.         }
  71.     }
  72. }
  73.  
  74. void TestProducerConsumer() {
  75.     Synchronized<deque<int>> common_queue;
  76.  
  77.     auto consumer = async(Consume, ref(common_queue));
  78.  
  79.     const size_t item_count = 100000;
  80.     for (size_t i = 1; i <= item_count; ++i) {
  81.         common_queue.GetAccess().ref_to_value.push_back(i);
  82.     }
  83.     common_queue.GetAccess().ref_to_value.push_back(-1);
  84.  
  85.     vector<int> expected(item_count);
  86.     iota(begin(expected), end(expected), 1);
  87.     ASSERT_EQUAL(consumer.get(), expected);
  88. }
  89.  
  90. int main() {
  91.     Synchronized<int> s_int;
  92.     {
  93.       auto access = s_int.GetAccess();
  94.       access.ref_to_value = 5;
  95.     }
  96.     ASSERT_EQUAL(s_int.GetAccess().ref_to_value, 5);
  97. }
Advertisement
Add Comment
Please, Sign In to add comment