Sobes.tech
Middle+
317

Бир иштеке ичинде ката чыкканын кантип текшерсе болот?

AIден жооп

sobes.tech 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 же кол менен башкаруу көбүрөөк татаал синхрондоо сценарийлеринде пайдалуу болушу мүмкүн.