Sobes.tech
Middle+

როგორ შემოწმოთ, მოხდა თუ არა გამონაკლისი ერთ-ერთ ნაკადში?

sobes.tech AI

პასუხი AI-სგან

Հոսքում արտակարգ իրավիճակների ստուգման համար կարելի է օգտագործել մի քանի մոտեցումներ՝ կախված այն բանից, թե ինչպես է հոսքը ստեղծվել և ինչպես են մշակվում նրա արդյունքները:

  1. Օգտագործել std::future և std::async: Եթե հոսքը սկսվել է std::async-ի միջոցով, արդյունքը կլինի std::future օբյեկտ։ Այս օբյեկտի վրա get() կամ wait() մեթոդների կանչելը կբերի այն, որ հոսքում արտակարգ իրավիճակով նետված արտակարգ իրավիճակը կրկին նետվի վերադառնալու հոսքում:

    #include <future>
    #include <iostream>
    #include <stdexcept>
    
    void thread_function() {
        throw std::runtime_error("Հոսքում սխալ!");
    }
    
    int main() {
        std::future<void> future = std::async(std::launch::async, thread_function);
    
        try {
            future.get(); // սպասում է ավարտին և նետում է արտակարգ իրավիճակ, եթե կա
        } catch (const std::exception& e) {
            std::cerr << "Հայտնաբերված արտակարգ իրավիճակ հոսքից՝ " << e.what() << std::endl;
        }
    
        return 0;
    }
    
  2. Օգտագործել std::promise և std::future: Կարող եք բացահայտ փոխանցել std::promise հոսքին կամ պահել այն հոսքից դուրս՝ հոսքը կարողանա պահպանել արտակարգ իրավիճակը:

    #include <future>
    #include <iostream>
    #include <thread>
    #include <stdexcept>
    
    void thread_function_with_promise(std::promise<void>&& promise) {
        try {
            throw std::runtime_error("Նոր սխալ հոսքում!");
            promise.set_value(); // սահմանել արժեքը (եթե արտակարգ իրավիճակ չլիներ)
        } catch (...) {
            promise.set_exception(std::current_exception()); // արտակարգ իրավիճակը պահպանել
        }
    }
    
    int main() {
        std::promise<void> promise;
        std::future<void> future = promise.get_future();
    
        std::thread t(thread_function_with_promise, std::move(promise));
    
        try {
            future.get(); // սպասում է ավարտին և նետում է պահպանված արտակարգ իրավիճակը
        } catch (const std::exception& e) {
            std::cerr << "Հայտնաբերված արտակարգ իրավիճակ (promise-ով)՝ " << e.what() << std::endl;
        }
    
        t.join(); // սպասում է հոսքի ավարտին
    
        return 0;
    }
    
  3. Հատուկ կառավարման արտակարգ իրավիճակներ: Հոսքը կարող է բռնել արտակարգ իրավիճակը ներսում և պահպանել այն (օրինակ, std::exception_ptr-ում) կամ տեղեկացնել այլ հոսքին դրա մասին (օրինակ, ատոմային փոփոխականի կամ մյուտեքսի միջոցով):

    #include <iostream>
    #include <thread>
    #include <atomic>
    #include <exception>
    #include <mutex>
    #include <condition_variable>
    
    std::exception_ptr global_exception_ptr = nullptr;
    std::mutex exception_mutex;
    std::condition_variable exception_cv;
    bool exception_occurred = false;
    
    void thread_function_manual() {
        try {
            throw std::logic_error("Логическая ошибка в потоке!");
        } catch (...) {
            std::lock_guard<std::mutex> lock(exception_mutex);
            global_exception_ptr = std::current_exception(); // Сохранить текущее исключение
            exception_occurred = true;
            exception_cv.notify_one(); // Уведомить ожидающий поток
        }
    }
    
    int main() {
        std::thread t(thread_function_manual);
    
        // Основной поток может ждать уведомления об исключении
        std::unique_lock<std::mutex> lock(exception_mutex);
        exception_cv.wait(lock, []{ return exception_occurred; });
    
        if (global_exception_ptr) {
            try {
                std::rethrow_exception(global_exception_ptr); // Перебросить сохраненное исключение
            } catch (const std::exception& e) {
                std::cerr << "Поймано исключение из потока (ручное управление): " << e.what() << std::endl;
            }
        }
    
        t.join();
    
        return 0;
    }
    

Ընտրությունը կախված է կոնտեքստից: std::async-ը և std::future-ը առավել հարմար են արդյունքը կամ արտակարգ իրավիճակը ստանալու համար առանձին առաջադրանքից, իսկ std::promise/std::future կամ ձեռքով կառավարման մեթոդները կարող են օգտակար լինել ավելի բարդ սինխրոնացման դեպքերում։