Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Qt и кроссплатформенное программирование С/С++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.10.2014, 19:53   #1
sider2302
Новичок
Джуниор
 
Регистрация: 24.10.2014
Сообщений: 2
По умолчанию Особождение ресурсов в потоках

Доброго времени суток! Программа вываливается с сообщением terminate called without an active exception во время уничтожения вектора с shared_ptr<thread>. В отладчике увидел, что это происходит в десткуторе класса std::thread, когда происходит вызов std::terminate(). Если использовать не std::shared_ptr, а обычные указатели, то когда происходит delete указателя на объект std::thread, то программа вываливается с тем же сообщением. То есть, программа вываливается при уничтожении объекта u в main. ОСь: Ubuntu 14.04 amd64. Компилятор: gcc 4.8.2. В чем может быть проблема и как адекватно освобождать ресурсы, выделенные под потоки, и как по-нормальному организовывать пул потоков, а не через std::vector и std::shared_ptr?
Код:
#ifndef UTILITY_HPP
#define UTILITY_HPP

#include <tr1/functional>
#include <vector>
#include <thread>
#include <mutex>
#include <chrono>

template<typename T>
/**
 * @class thread_safety_vector
 * @brief потокобезопасный вектор
 */
class thread_safety_vector
{
    std::recursive_mutex insert_mutex;
    std::recursive_mutex clear_mutex;
    std::vector<T> vector;
public:

    typedef typename std::vector<T>::iterator iterator;

    thread_safety_vector() = default;
    thread_safety_vector(const thread_safety_vector<T>&) = default;

    void push_back(T val){
        std::lock_guard<std::recursive_mutex> locker(insert_mutex);
        vector.push_back(val);
    }

    iterator begin()
    {
        return vector.begin();
    }

    iterator end()
    {
        return vector.end();
    }

    void clear()
    {
        std::lock_guard<std::recursive_mutex> locker(clear_mutex);
        vector.clear();
    }

    iterator insert(iterator pos, const T &v)
    {
        std::lock_guard<std::recursive_mutex> locker(insert_mutex);
        return vector.insert(pos, v);
    }

    ~thread_safety_vector() = default;
};

/**
 * @class task_thread
 * @brief класс задачи
 */
class task_thread
{
    /**
     * @brief выполняет активное ожидание
     * @param dt время ожидания в милисекундах
     */
    inline void active_wait(int dt)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(dt));
    }

public:
    task_thread() = default;

    /**
     * @brief operator () поток задачи
     */
    inline void operator()(const std::tr1::function<void()>& t, int r, int d){
        //выполняем задачу раз
        while(--r >= 0){
            active_wait(d); //ждем заданное время
            t(); //запускаем задачу
        }
    }

    ~task_thread()=default;
};



/**
 * @class utility
 * @brief Запускает задачу n раз через каждые t милисекунд
 */
class utility
{   
    typedef thread_safety_vector<std::shared_ptr<std::thread>> task_container;
    task_container tasks; //массив задач

    void _start_tasks()
    {
        for(auto &t : tasks){
            t->join();
        }
    }

public:
    utility()=default;

    /**
     * @brief запускает задачу task в отдельном потоке, и выполняет её repeatn раз через каждые ts милисекунд
     * @param repeatn количество повторов задачи
     * @param tms время, через которое задача запускается
     * @param task задача
     */
    inline void join_task(int repeatn, int ts, const std::tr1::function<void()>& task)
    {
        tasks.push_back(std::make_shared<std::thread>(task_thread(), task, repeatn, ts));
    }

    /**
     * @brief start_tasks запускает задачи на выполнение в отдельном потоке
     */
    inline void start_tasks()
    {
        std::thread st(&utility::_start_tasks, this);
        st.join();
    }

    ~utility()=default;
};

#endif // UTILITY_HPP

#include <iostream>

#include "utility.hpp"

//задачи для тестирования

void hw_task()
{
    std::cout << "Hello, World!!!\n";
}

void my_task()
{
    std::cout << "My Task\n";
}

int main()
{
    utility u;

    for(int i = 0; i < 999; i++){
        u.join_task(5, 1000, hw_task);
        u.join_task(10, 1000, my_task);
    }

    u.start_tasks();

    for(int i = 0; i < 999; i++){
        u.join_task(5, 1000, hw_task);
        u.join_task(10, 1000, my_task);
    }

    return 0;
}

Последний раз редактировалось Stilet; 24.10.2014 в 20:01.
sider2302 вне форума Ответить с цитированием
Старый 25.10.2014, 13:46   #2
sider2302
Новичок
Джуниор
 
Регистрация: 24.10.2014
Сообщений: 2
По умолчанию

Разобрался, нужно было в деструкторе класса utility дождаться завершения всех потоков
sider2302 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка в потоках FreeZon Общие вопросы Delphi 5 10.02.2014 17:39
Прокси в потоках admin22 Общие вопросы Delphi 7 02.01.2013 12:05
Сокеты в потоках unmazable Общие вопросы Delphi 0 12.03.2012 13:35
Canvas в потоках demigod82 Общие вопросы Delphi 9 05.03.2012 08:51
синхронизация в потоках xrob Общие вопросы Delphi 8 15.11.2010 17:25