1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/sogou-workflow

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
about-timer.md 7.1 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 01.03.2025 10:20 552780a

О задачах таймера

Задачи таймера предназначены для ожидания определённого времени без использования потока. Уведомление о завершении таймера осуществляется через коллбэк.

Создание задачи таймера

Класс WFTaskFactory включает четыре метода, связанных с таймерами:

using timer_callback_t = std::function<void (WFTimerTask *)>;

class WFTaskFactory
{
    ...
public:
    static WFTimerTask *create_timer_task(time_t seconds, long nanoseconds,
                                          timer_callback_t callback);

    static WFTimerTask *create_timer_task(const std::string& timer_name,
                                          time_t seconds, long nanoseconds,
                                          timer_callback_t callback);

    static int cancel_by_name(const std::string& timer_name)
    {
        cancel_by_name(const std::string& timer_name, (size_t)-1);
    }

    static int cancel_by_name(const std::string& timer_name, size_t max);
};

Для создания задачи таймера используются два параметра: seconds и nanoseconds, которые указывают время ожидания.

  • Параметр seconds может принимать значение -1, что создаст бесконечный таймер, обычно используемый для названных таймеров, чтобы иметь возможность отменить его позже.
  • Значение параметра nanoseconds должно находиться в диапазоне [0, 1000000000). В противном случае, после запуска таймера будет немедленно возращена ошибка с кодом EINVAL.

При создании задачи таймера можно передать имя таймера (timer_name). Это имя используется для отмены задачи таймера через метод cancel_by_name.

Задачи таймера также являются типом задачи, поэтому они могут использоваться так же, как и другие типы задач. Они имеют поле user_data, которое можно использовать для хранения данных пользователя.

Отмена задачи таймера

Если при создании задачи таймера было указано имя, то эту задачу можно отменить до её выполнения.

Отмена задачи таймера выполняется через метод WFTaskFactory::cancel_by_name. По умолчанию этот метод отменяет все задачи таймера с данным именем. Однако, вы можете передать параметр max, который ограничит количество отмененных задач.

Пример программы, демонстрирующей использование задачи таймера:

#include <stdio.h>
#include "workflow/WFTaskFactory.h"

int main()
{
    WFTimerTask *timer = WFTaskFactory::create_timer_task("test", 10000, 0, [](WFTimerTask *){
        printf("таймер вызван обратно, состояние = %d, ошибка = %d.\n", task->get_state(), task->get_error());
    });

    WFTaskFactory::cancel_by_name("test");

    timer->start();

    getchar();
    return 0;
}

Программа сразу выводит сообщение 'таймер вызван обратно, состояние = 1, ошибка = 125.', поскольку задача была отменена до начала выполнения. Поэтому, если задача таймера была отменена до запуска, она немедленно вызывает обратный коллбэк, состояние равно WFT_STATE_SYS_ERROR, а код ошибки равен ECANCELED.

Необходимо отметить, что использование названных таймеров требует больше затрат по сравнению с анонимными таймерами, поскольку требуется поддерживать таблицу поиска и выполнять операции блокировки/разблокировки. Если нет необходимости отменять таймер заранее, лучше не указывать имя при создании задачи таймера.

Прерывание задачи таймера при выходе программы

Как описано в разделе О выходе программы, когда основной метод завершён или вызван exit(), все задачи должны завершиться и вызвать обратные коллбэки. При этом новые задачи не должны быть запущены.

Это может привести к проблеме, если период таймера очень велик. В этом случае, если таймер не может быть прерван, программа может долго ждать завершения таймера перед тем, как завершиться.

На практике, выход программы может прервать задачу таймера, заставив её вернуться к обратному коллбэку. Если задача таймера была прервана выходом программы, get_state() вернет состояние WFT_STATE_ABORTED.

Ниже представлен пример программы, которая каждую секунду получает HTTP страницу. Когда все URL были обработаны, программа завершается немедленно, без ожидания завершения задачи таймера.

bool program_terminate = false;

void timer_callback(WFTimerTask *timer)
{
    mutex.lock();
    if (!program_terminate)
    {
        WFHttpTask *task;
        if (urls_to_fetch > 0)
        {
            task = WFTaskFactory::create_http_task(...);
            series_of(timer)->push_back(task);
        }

        series_of(timer)->push_back(WFTaskFactory::create_timer_task(1, 0, timer_callback));
    }
    mutex.unlock();
}

...
int main()
{
    ...
    /* все URL обработаны */
    mutex.lock();
    program_terminate = true;
    mutex.unlock();
    return 0;
}

В данном примере, метод timer_callback должен проверять условие program_terminate внутри блокировки, чтобы избежать запуска новых задач после завершения программы.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/sogou-workflow.git
git@api.gitlife.ru:oschina-mirror/sogou-workflow.git
oschina-mirror
sogou-workflow
sogou-workflow
master