Advertisement
khaze1

cafeteria

Oct 18th, 2024 (edited)
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.49 KB | None | 0 0
  1. #ifdef _WIN32
  2. #include <sdkddkver.h>
  3. #endif
  4.  
  5. #include <boost/asio/io_context.hpp>
  6. #include <boost/asio/steady_timer.hpp>
  7. #include <boost/asio/strand.hpp>
  8. #include <boost/asio/bind_executor.hpp>
  9. #include <atomic>
  10. #include <memory>
  11. #include <utility>
  12.  
  13. #include "hotdog.h"
  14. #include "result.h"
  15.  
  16. namespace net = boost::asio;
  17.  
  18. // Функция-обработчик операции приготовления хот-дога
  19. using HotDogHandler = std::function<void(Result<HotDog> hot_dog)>;
  20.  
  21. class ThreadChecker {
  22. public:
  23.     explicit ThreadChecker(std::atomic_int& counter)
  24.         : counter_{counter} {
  25.     }
  26.  
  27.     ThreadChecker(const ThreadChecker&) = delete;
  28.     ThreadChecker& operator=(const ThreadChecker&) = delete;
  29.  
  30.     ~ThreadChecker() {
  31.         // assert выстрелит, если между вызовом конструктора и деструктора
  32.         // значение expected_counter_ изменится
  33.         assert(expected_counter_ == counter_);
  34.     }
  35.  
  36. private:
  37.     std::atomic_int& counter_;
  38.     int expected_counter_ = ++counter_;
  39. };
  40.  
  41.  
  42. class Order : public std::enable_shared_from_this<Order> {
  43. public:
  44.     Order(HotDogHandler handler, GasCooker& cooker, Store& store, HotDogMaker& maker, net::io_context& io)
  45.             : handler_(std::move(handler)), io_(io), cooker_(cooker), maker_(maker)
  46.     {
  47.         std::mutex mut;
  48.         std::lock_guard lg{mut};
  49.         bread_ = store.GetBread();
  50.         sausage_ = store.GetSausage();
  51.         order_id_ = bread_->GetId();
  52.         logger_.SetId(std::to_string(order_id_));
  53.     }
  54.  
  55.     void Execute() {
  56.         CookSausage();
  57.         BakeBread();
  58.     }
  59.  
  60. private:
  61.     void CookSausage() {
  62.         sausage_->StartFry(cooker_, [self = shared_from_this()]{
  63.                 self->logger_.LogMessage("Sausage "s + std::to_string(self->sausage_->GetId()) + " start frying"s);
  64.                 net::post(self->io_, [self] {
  65.                    self->sausage_timer_.async_wait(net::bind_executor(self->strand_, [self] (sys::error_code ec) {
  66.                         self->sausage_->StopFry();
  67.                         self->OnCookedSausage({});
  68.                     }));
  69.                 });
  70.             });
  71.  
  72.     }
  73.  
  74.     void BakeBread() {
  75.         bread_->StartBake(cooker_, [self = shared_from_this()]{
  76.                 self->logger_.LogMessage("Bread "s + std::to_string(self->bread_->GetId()) + " start bake"s);
  77.                 self->bread_timer_.async_wait(net::bind_executor(self->strand_, [self] (sys::error_code ec) {
  78.                     self->bread_->StopBaking();
  79.                     self->OnBakedBread(ec);
  80.                 }));
  81.             });
  82.     }
  83.  
  84.     void OnBakedBread(sys::error_code ec) {
  85.         ThreadChecker tc{counter_};
  86.         if (ec) {
  87.             logger_.LogMessage("Bakining error: "s + ec.what());
  88.         } else {
  89.             logger_.LogMessage("Bread "s + std::to_string(bread_->GetId()) + " stop bake"s);
  90.         }
  91.         CheckReadiness(ec);
  92.     }
  93.  
  94.     void OnCookedSausage(sys::error_code ec) {
  95.         ThreadChecker tc{counter_};
  96.         if (ec) {
  97.             logger_.LogMessage("Frying error: "s + ec.what());
  98.         } else if (!sausage_->IsCooked()) {
  99.             logger_.LogMessage("The sausage didn't fry, although it should have"s);
  100.         } else {
  101.             logger_.LogMessage("Sausage "s + std::to_string(sausage_->GetId()) + " stop frying"s);
  102.         }
  103.         CheckReadiness(ec);
  104.     }
  105.  
  106.     void CheckReadiness(sys::error_code ec) {
  107.         logger_.LogMessage("Checking readiness in thread "s + std::to_string(std::hash<std::thread::id>{}(std::this_thread::get_id())));
  108.         if (delivered_) {
  109.             logger_.LogMessage("Already delivered"s);
  110.             return;
  111.         }
  112.         if (ec) {
  113.             Deliver(ec);
  114.             logger_.LogMessage("Delivering error messege"s);
  115.         }
  116.         if (sausage_->IsCooked() && bread_->IsCooked()) {
  117.             logger_.LogMessage("Bread and Sausage are cooked, about to create HotDog"s);
  118.             Deliver({});
  119.         }
  120.         if (sausage_->IsCooked()) {
  121.  
  122.         }
  123.         //logger_.LogMessage("Something went wrong"s);
  124.     }
  125.  
  126.     void Deliver(sys::error_code ec) {
  127.         if (ec) {
  128.             handler_(Result<HotDog>(std::make_exception_ptr(std::runtime_error{ec.what()})));
  129.         }
  130.         try {
  131.             handler_(Result<HotDog>(maker_.GetHotDog(sausage_, bread_)));
  132.         } catch(...) {
  133.             handler_(Result<HotDog>::FromCurrentException());
  134.         }
  135.     }
  136.  
  137.     void MakeHotDog() {
  138.         try {
  139.  
  140.         } catch(std::exception& e) {
  141.         }
  142.     }
  143. private:
  144.     using Strand = net::strand<net::io_context::executor_type>;
  145.     HotDogHandler handler_;
  146.     net::io_context& io_;
  147.     std::shared_ptr<Sausage> sausage_;
  148.     std::shared_ptr<Bread> bread_;
  149.     GasCooker& cooker_;
  150.     HotDogMaker& maker_;
  151.     net::steady_timer sausage_timer_{io_, 1500ms};
  152.     net::steady_timer bread_timer_{io_, 1s};
  153.     std::atomic_int counter_{0};
  154.     Strand strand_ {net::make_strand(io_)};
  155.     bool delivered_ = false;
  156.     int order_id_;
  157.     Logger logger_;
  158. };
  159. // Класс "Кафетерий". Готовит хот-доги
  160. class Cafeteria {
  161. public:
  162.     explicit Cafeteria(net::io_context& io)
  163.         : io_{io} {
  164.     }
  165.  
  166.     // Асинхронно готовит хот-дог и вызывает handler, как только хот-дог будет готов.
  167.     // Этот метод может быть вызван из произвольного потока
  168.     void OrderHotDog(HotDogHandler handler) {
  169.         // TODO: Реализуйте метод самостоятельно
  170.         // При необходимости реализуйте дополнительные классы
  171.         std::make_shared<Order>(std::move(handler), *gas_cooker_, store_, maker_, io_)->Execute();
  172.    }
  173.  
  174. private:
  175.     net::io_context& io_;
  176.     // Используется для создания ингредиентов хот-дога
  177.     Store store_;
  178.     // Газовая плита. По условию задачи в кафетерии есть только одна газовая плита на 8 горелок
  179.     // Используйте её для приготовления ингредиентов хот-дога.
  180.     // Плита создаётся с помощью make_shared, так как GasCooker унаследован от
  181.     // enable_shared_from_this.
  182.     std::shared_ptr<GasCooker> gas_cooker_ = std::make_shared<GasCooker>(io_);
  183.     HotDogMaker maker_;
  184. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement