Можно ли принудительно завершить работу std::sort?

У меня есть основной поток, который содержит в себе бесконечный цикл, который дожидается другой поток, занимающийся сортировкой.

// Инициализация потока для работы с сортировкой файла
const poco::Runnable::Ptr sortingRunnable(new SortingRunnable(this));
poco::Thread sortingThread;

// Флаг, отсортирован ли файл
_isSorted = false;

// Запуск сортировки 
sortingThread.start(sortingRunnable);

// Выставление ProgressBar в бесконечное состояние
_processForm->showProgress();
_processForm->initProgress(0, 0);

// Скрываем поля, оставив только ProgressBar
_processForm->hideLabelsAndCounters();

// Перерисовываем ProgressBar для прокрутки "бесконечной" загрузки
for (;;)
{
    _processForm->repaintProgress();

    // Если файл будет отсортирован, но выходим из цикла
    if (_isSorted)
        break;

    // Если во время сортировки файла, пользователь нажмёт ( Отмена ), то прозводим выход 
    checkApplicationMessage();

    // Принудительно вызываю обработку накопившихся событий
    QApplication::processEvents();
}

// Ждём поток, отвечающий за сортировку
sortingThread.join();

Как можете видеть я создаю Runnable библиотеки poco, и в нём вызываю асинхронную сортировку. Соотвественно я и дожидаюсь результата этой сортировки в бексонечном цикле цикле. Сама сортировка вот:

class SortingRunnable : public poco::Runnable {
public:
explicit SortingRunnable(ImportMaster* import) : _import(import) {}
~SortingRunnable() {}
void run() override
{
    auto sorting = [&](const QStringList& str1, const QStringList& str2) -> bool
    {
        if (str1.empty() || str2.empty())
            return false;

        QChar char1;
        QChar char2;

        if (!str1[0].isEmpty() && !str2[0].isEmpty())
        {
            char1 = str1[0][0];
            char2 = str2[0][0];
        }

        const poco::UInt8 SYMBOL = 0x0000007E;

        if ((char1 == SYMBOL && char2 == SYMBOL) || (char1 != SYMBOL && char2 != SYMBOL))
            return naturalSorting(str1.join(',').toStdString(), str2.join(',').toStdString());

        if (char1 != SYMBOL && char2 == SYMBOL)
            return false;

        if (char1 == SYMBOL && char2 != SYMBOL)
            return true;

        return false;
    };

    std::sort(_import->_strings.begin(), _import->_strings.end(), sorting);

    _import->_isSorted = true;
}

private:
    ImportMaster* _import;
};

Теперь основной вопрос. Функция checkApplicationMessage(); вызывает обработку отмены процесса импорта, который в основной поток кидает исключение, которое я могу успешно отловить и обработать как мне нужно. Но как мне сказать потоку Runnable остановить процесс std::sort (сортировки)?


Ответы (1 шт):

Автор решения: Larsan Vtvoyrotovich

Решением для данной задачи я нашёл один путь. На просторах интернета обнаружил, что можно кидать исключения в std::sort обработке. Что я и сделал, создал атомарный флаг, который выставляется во время выброса исключения.

void run() override
{
    auto sorting = [&](const QStringList& str1, const QStringList& str2) -> bool
    {
        if (_import->_isSortedStoped)
            throw poco::Exception("Stoped sorting");

        if (str1.empty() || str2.empty())
            return false;

        QChar char1;
        QChar char2;

        if (!str1[0].isEmpty() && !str2[0].isEmpty())
        {
            char1 = str1[0][0];
            char2 = str2[0][0];
        }

        const poco::UInt8 SYMBOL = 0x0000007E;

        if ((char1 == SYMBOL && char2 == SYMBOL) || (char1 != SYMBOL && char2 != SYMBOL))
            return naturalSorting(str1.join(',').toStdString(), str2.join(',').toStdString());

        if (char1 != SYMBOL && char2 == SYMBOL)
            return false;

        if (char1 == SYMBOL && char2 != SYMBOL)
            return true;

        return false;
    };

    try
    {
        std::sort(_import->_strings.begin(), _import->_strings.end(), sorting);
    }
    catch (...)
    {
        _import->_isSorted = true;
        return;
    }

    _import->_isSorted = true;
}

Для ловли исключения в основном потоке создал обёртку над функцией и разорвал поток обработки detach`ем.

// Инициализация потока для работы с сортировкой файла
const poco::Runnable::Ptr sortingRunnable(new SortingRunnable(this));
poco::Thread sortingThread;

// Флаг, отсортирован ли файл
_isSorted = false;
_isSortedStoped = false;

// Запуск сортировки 
sortingThread.start(sortingRunnable);
sortingThread.detach();

// Выставление ProgressBar в бесконечное состояние
_processForm->showProgress();
_processForm->initProgress(0, 0);

// Скрываем поля, оставив только ProgressBar
_processForm->hideLabelsAndCounters();

// Перерисовываем ProgressBar для прокрутки "бесконечной" загрузки
for (;;)
{
    _processForm->repaintProgress();

    // Если файл будет отсортирован, но выходим из цикла
    if (_isSorted)
        break;

    // Если во время сортировки файла, пользователь нажмёт ( Отмена ), то прозводим выход 
    try
    {
        checkApplicationMessage();
    }
    catch (poco::Exception& ex)
    {
        _isSortedStoped = true;
        throw ex;
    }

        // Принудительно вызываю обработку накопившихся событий
    QApplication::processEvents();
}

if (sortingThread.joinable())
    // Ждём поток, отвечающий за сортировку
    sortingThread.join();

Теперь всё стало работать как мне и нужно было.

→ Ссылка