shushus

Спринт 11. Умный указатель weak_ptr.

Mar 26th, 2023
408
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.85 KB | None | 0 0
  1. -----------------------------------------------------------------------
  2. cache.cpp
  3. -----------------------------------------------------------------------
  4. #include <cassert>
  5. #include <iostream>
  6. #include <memory>
  7. #include <string>
  8. #include <string_view>
  9. #include <unordered_map>
  10.  
  11. template <typename Key, typename Value, typename ValueFactoryFn>
  12. class Cache {
  13. public:
  14.     Cache() = default;
  15.  
  16.     explicit Cache(ValueFactoryFn value_factory) : value_factory_(value_factory) {}
  17.  
  18.     std::shared_ptr<Value> GetValue(const Key& key) {
  19.    
  20.         std::shared_ptr<Value> temp;
  21.        
  22.         if (value_map_.count(key)) {
  23.             if (value_map_[key].expired()) {
  24.                 temp = value_factory_(key);
  25.                 value_map_[key] = temp;
  26.             }
  27.            
  28.             return (value_map_[key]).lock();  
  29.         }
  30.        
  31.         temp = value_factory_(key);
  32.         value_map_[key] = temp;
  33.         return (value_map_[key]).lock();
  34.     }
  35.    
  36. private:
  37.     ValueFactoryFn value_factory_;
  38.     std::unordered_map<Key, std::weak_ptr<Value>> value_map_;
  39. };
  40.  
  41. class Object {
  42. public:
  43.     explicit Object(std::string id) : id_(std::move(id)) {
  44.         using namespace std;
  45.         cout << "Object '"sv << id_ << "' has been created"sv << endl;
  46.     }
  47.  
  48.     const std::string& GetId() const {
  49.         return id_;
  50.     }
  51.  
  52.     ~Object() {
  53.         using namespace std;
  54.         cout << "Object '"sv << id_ << "' has been destroyed"sv << endl;
  55.     }
  56.  
  57. private:
  58.     std::string id_;
  59. };
  60.  
  61. using ObjectPtr = std::shared_ptr<Object>;
  62.  
  63. struct ObjectFactory {
  64.     ObjectPtr operator()(std::string id) const {
  65.         return std::make_shared<Object>(std::move(id));
  66.     }
  67. };
  68.  
  69. void Test1() {
  70.     using namespace std;
  71.     ObjectPtr alice1;
  72.     Cache<string, Object, ObjectFactory> cache;
  73.  
  74.     alice1 = cache.GetValue("Alice"s);
  75.     auto bob = cache.GetValue("Bob"s);
  76.  
  77.     assert(alice1 != bob);
  78.     assert(alice1->GetId() == "Alice"s);
  79.     assert(bob->GetId() == "Bob"s);
  80.  
  81.     auto alice2 = cache.GetValue("Alice"s);
  82.     assert(alice1 == alice2);
  83.  
  84.     weak_ptr alice_wp{alice1};
  85.     alice1.reset();
  86.     assert(!alice_wp.expired());
  87.     cout << "---"sv << endl;
  88.     alice2.reset();
  89.  
  90.     assert(alice_wp.expired());
  91.     cout << "---"sv << endl;
  92.  
  93.  
  94.     alice1 = cache.GetValue("Alice"s);
  95.     cout << "---"sv << endl;
  96. }
  97.  
  98. struct Book {
  99.     Book(std::string title, std::string content)
  100.         : title(std::move(title))
  101.         , content(std::move(content)) {
  102.     }
  103.  
  104.     std::string title;
  105.     std::string content;
  106. };
  107.  
  108. class BookLoader {
  109. public:
  110.     using BookStore = std::unordered_map<std::string, std::string>;
  111.  
  112.     explicit BookLoader(const BookStore& store, size_t& load_count) : store_(store),
  113.                                                                       load_count_(load_count) {}
  114.  
  115.     std::shared_ptr<Book> operator()(const std::string& title) const {
  116.        
  117.         if (store_.count(title)) {
  118.             ++load_count_;  
  119.             return std::make_shared<Book>(title, store_.at(title));
  120.         } else {
  121.             throw std::out_of_range("Not implemented");
  122.         }
  123.     }
  124.  
  125. private:
  126.     const BookStore& store_;
  127.     size_t& load_count_;
  128. };
  129.  
  130. void Test2() {
  131.     using namespace std;
  132.  
  133.     BookLoader::BookStore books{
  134.         {"Sherlock Holmes"s,
  135.          "To Sherlock Holmes she is always the woman. I have seldom heard him mention her under any other name."s},
  136.         {"Harry Potter"s, "Chapter 1. The boy who lived. ...."s},
  137.     };
  138.     using BookCache = Cache<string, Book, BookLoader>;
  139.  
  140.     size_t load_count = 0;
  141.  
  142.     BookCache book_cache{BookLoader{books, load_count}};
  143.  
  144.     auto book1 = book_cache.GetValue("Sherlock Holmes"s);
  145.     assert(book1);
  146.     assert(book1->title == "Sherlock Holmes"s);
  147.     assert(book1->content == books.at(book1->title));
  148.     assert(load_count == 1);
  149.  
  150.     auto book2 = book_cache.GetValue("Sherlock Holmes"s);
  151.     assert(book2);
  152.     assert(book1 == book2);
  153.     assert(load_count == 1);
  154.  
  155.     weak_ptr<Book> weak_book{book1};
  156.     assert(!weak_book.expired());
  157.     book1.reset();
  158.     book2.reset();
  159.  
  160.     assert(weak_book.expired());
  161.  
  162.     book1 = book_cache.GetValue("Sherlock Holmes"s);
  163.     assert(load_count == 2);
  164.     assert(book1);
  165.  
  166.     try {
  167.         book_cache.GetValue("Fifty Shades of Grey"s);
  168.         assert(false);
  169.     } catch (const std::out_of_range&) {
  170.  
  171.     } catch (...) {
  172.         cout << "Unexpected exception"sv << endl;
  173.     }
  174.  
  175.     assert(load_count == 2);
  176.  
  177.     books["Fifty Shades of Grey"s] = "I scowl with frustration at myself in the mirror..."s;
  178.  
  179.     try {
  180.         auto book = book_cache.GetValue("Fifty Shades of Grey"s);
  181.  
  182.         assert(book->content == books.at("Fifty Shades of Grey"s));
  183.     } catch (...) {
  184.         assert(false);
  185.     }
  186.  
  187.     assert(load_count == 3);
  188. }
  189.  
  190. int main() {
  191.     Test1();
  192.     Test2();
  193. }
Advertisement
Add Comment
Please, Sign In to add comment