Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifdef _WIN32
- #include <sdkddkver.h>
- #endif
- #include <boost/asio/io_context.hpp>
- #include <boost/asio/steady_timer.hpp>
- #include <boost/asio/strand.hpp>
- #include <boost/asio/bind_executor.hpp>
- #include <atomic>
- #include <memory>
- #include <utility>
- #include "hotdog.h"
- #include "result.h"
- namespace net = boost::asio;
- // Функция-обработчик операции приготовления хот-дога
- using HotDogHandler = std::function<void(Result<HotDog> hot_dog)>;
- class ThreadChecker {
- public:
- explicit ThreadChecker(std::atomic_int& counter)
- : counter_{counter} {
- }
- ThreadChecker(const ThreadChecker&) = delete;
- ThreadChecker& operator=(const ThreadChecker&) = delete;
- ~ThreadChecker() {
- // assert выстрелит, если между вызовом конструктора и деструктора
- // значение expected_counter_ изменится
- assert(expected_counter_ == counter_);
- }
- private:
- std::atomic_int& counter_;
- int expected_counter_ = ++counter_;
- };
- class Order : public std::enable_shared_from_this<Order> {
- public:
- Order(HotDogHandler handler, GasCooker& cooker, Store& store, HotDogMaker& maker, net::io_context& io)
- : handler_(std::move(handler)), io_(io), cooker_(cooker), maker_(maker)
- {
- std::mutex mut;
- std::lock_guard lg{mut};
- bread_ = store.GetBread();
- sausage_ = store.GetSausage();
- order_id_ = bread_->GetId();
- logger_.SetId(std::to_string(order_id_));
- }
- void Execute() {
- CookSausage();
- BakeBread();
- }
- private:
- void CookSausage() {
- sausage_->StartFry(cooker_, [self = shared_from_this()]{
- self->logger_.LogMessage("Sausage "s + std::to_string(self->sausage_->GetId()) + " start frying"s);
- net::post(self->io_, [self] {
- self->sausage_timer_.async_wait(net::bind_executor(self->strand_, [self] (sys::error_code ec) {
- self->sausage_->StopFry();
- self->OnCookedSausage({});
- }));
- });
- });
- }
- void BakeBread() {
- bread_->StartBake(cooker_, [self = shared_from_this()]{
- self->logger_.LogMessage("Bread "s + std::to_string(self->bread_->GetId()) + " start bake"s);
- self->bread_timer_.async_wait(net::bind_executor(self->strand_, [self] (sys::error_code ec) {
- self->bread_->StopBaking();
- self->OnBakedBread(ec);
- }));
- });
- }
- void OnBakedBread(sys::error_code ec) {
- ThreadChecker tc{counter_};
- if (ec) {
- logger_.LogMessage("Bakining error: "s + ec.what());
- } else {
- logger_.LogMessage("Bread "s + std::to_string(bread_->GetId()) + " stop bake"s);
- }
- CheckReadiness(ec);
- }
- void OnCookedSausage(sys::error_code ec) {
- ThreadChecker tc{counter_};
- if (ec) {
- logger_.LogMessage("Frying error: "s + ec.what());
- } else if (!sausage_->IsCooked()) {
- logger_.LogMessage("The sausage didn't fry, although it should have"s);
- } else {
- logger_.LogMessage("Sausage "s + std::to_string(sausage_->GetId()) + " stop frying"s);
- }
- CheckReadiness(ec);
- }
- void CheckReadiness(sys::error_code ec) {
- logger_.LogMessage("Checking readiness in thread "s + std::to_string(std::hash<std::thread::id>{}(std::this_thread::get_id())));
- if (delivered_) {
- logger_.LogMessage("Already delivered"s);
- return;
- }
- if (ec) {
- Deliver(ec);
- logger_.LogMessage("Delivering error messege"s);
- }
- if (sausage_->IsCooked() && bread_->IsCooked()) {
- logger_.LogMessage("Bread and Sausage are cooked, about to create HotDog"s);
- Deliver({});
- }
- if (sausage_->IsCooked()) {
- }
- //logger_.LogMessage("Something went wrong"s);
- }
- void Deliver(sys::error_code ec) {
- if (ec) {
- handler_(Result<HotDog>(std::make_exception_ptr(std::runtime_error{ec.what()})));
- }
- try {
- handler_(Result<HotDog>(maker_.GetHotDog(sausage_, bread_)));
- } catch(...) {
- handler_(Result<HotDog>::FromCurrentException());
- }
- }
- void MakeHotDog() {
- try {
- } catch(std::exception& e) {
- }
- }
- private:
- using Strand = net::strand<net::io_context::executor_type>;
- HotDogHandler handler_;
- net::io_context& io_;
- std::shared_ptr<Sausage> sausage_;
- std::shared_ptr<Bread> bread_;
- GasCooker& cooker_;
- HotDogMaker& maker_;
- net::steady_timer sausage_timer_{io_, 1500ms};
- net::steady_timer bread_timer_{io_, 1s};
- std::atomic_int counter_{0};
- Strand strand_ {net::make_strand(io_)};
- bool delivered_ = false;
- int order_id_;
- Logger logger_;
- };
- // Класс "Кафетерий". Готовит хот-доги
- class Cafeteria {
- public:
- explicit Cafeteria(net::io_context& io)
- : io_{io} {
- }
- // Асинхронно готовит хот-дог и вызывает handler, как только хот-дог будет готов.
- // Этот метод может быть вызван из произвольного потока
- void OrderHotDog(HotDogHandler handler) {
- // TODO: Реализуйте метод самостоятельно
- // При необходимости реализуйте дополнительные классы
- std::make_shared<Order>(std::move(handler), *gas_cooker_, store_, maker_, io_)->Execute();
- }
- private:
- net::io_context& io_;
- // Используется для создания ингредиентов хот-дога
- Store store_;
- // Газовая плита. По условию задачи в кафетерии есть только одна газовая плита на 8 горелок
- // Используйте её для приготовления ингредиентов хот-дога.
- // Плита создаётся с помощью make_shared, так как GasCooker унаследован от
- // enable_shared_from_this.
- std::shared_ptr<GasCooker> gas_cooker_ = std::make_shared<GasCooker>(io_);
- HotDogMaker maker_;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement