Evgenii Legotckoi
28 грудня 2018 р. 20:09

Boost - виконання періодичних завдань за допомогою boost::thread

Пропоную написати невелику консольну програму, яка через рівні проміжки часу виконуватиме одне завдання.

Наприклад, програма запускається і робить 10 проб протягом 10 секунд, програма буде виводити інформацію про кількість зворотного відліку в консоль.

Програма працюватиме в такий спосіб.

Виконання періодичного завдання в консольному додатку


Структура проекту

У проекті використовується система складання CMake, тому структура проекту буде наступною.

Структура проекту PeriodicTask

CMakeLists.txt

Ось стандартна конфігурація CMake для збирання проекту.

cmake_minimum_required (VERSION 3.8)

project(Periodic)

set(CMAKE_CXX_STANDARD 17)
set(Boost_USE_STATIC_LIBS ON)

find_package(Boost 1.68 REQUIRED COMPONENTS thread)

set(SOURCE_FILES
        Periodic/main.cpp
        Periodic/PeriodicTask.cpp)

SET(HEADER_FILES
        Periodic/PeriodicTask.h)

if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS})
    add_executable(Periodic ${SOURCE_FILES} ${HEADER_FILES})
    target_link_libraries(Periodic ${Boost_LIBRARIES})
endif()

PeriodicTask.h

Заголовний файл періодичного завдання.

У найпростішому випадку для створення класу періодичного завдання нам знадобиться:

  • Тригерний період
  • об'єкт std::function для зберігання завдання
  • змінна bool для зупинки та запуску завдання. В даному прикладі ми не зупинятимемо завдання, але якщо додати методи run/stop, то реалізувати це цілком можливо.
  • boost::thread - потік, без якого цей функціонал не може бути реалізований
#pragma once

#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <functional>
#include <atomic>

class PeriodicTask
{
public:
    explicit PeriodicTask(const boost::chrono::milliseconds &period, const std::function<void()> &func);

    virtual ~PeriodicTask();

private:
    boost::chrono::milliseconds m_period;   // Task period
    std::function<void()> m_func;           // The function that will perform the periodic task
    std::atomic<bool> m_running;            // A variable that indicates that the task is running, with the help of it you can stop the task in the future
    boost::thread m_thread;                 // Task thread
};

PeriodicTask.cpp

#include "PeriodicTask.h"

PeriodicTask::PeriodicTask(const boost::chrono::milliseconds &period, const std::function<void()> &func) :
    m_period(period),
    m_func(func),
    m_running(true)
{
    // Create a stream object to perform a periodic task.
    m_thread = boost::thread([this]
    {
        while (m_running)
        {
            // To perform a task with a specific period, immerse the stream in a dream after each task execution.
            boost::this_thread::sleep_for(m_period);
            if (m_running)
            {
                // perform the task
                m_func();
            }
        }
    });
}

PeriodicTask::~PeriodicTask()
{
    // When destroying an object with a periodic task
    m_running = false;
    // interrupt the flow, otherwise the program will not release system resources until the flow comes out of sleep
    // this is critical if the trigger period of the task is measured in tens of seconds and more
    m_thread.interrupt();
    m_thread.join();
}

main.cpp

Файл із основною функцією. Коли ми створюємо об'єкт періодичного завдання, ми поміщаємо до нього лямбда-функцію як завдання, як найпростіший спосіб вказати, яку роботу потрібно виконати.

#include "PeriodicTask.h" // We connect the class header file to perform periodic tasks.

#include <iostream>

int main(int argc, const char* argv[])
{
    std::cout << "Start program" << std::endl;
    int count = 0;
    // Create a periodic task with a period of 1 second
    PeriodicTask p(boost::chrono::seconds{ 1 }, [&count]() {
        // Display the counter and increment it by one.
        std::cout << count++ << std::endl;
    });

    // Stop the main program flow for 10 seconds so that the periodic task can work 10 times.
    boost::this_thread::sleep_for(boost::chrono::seconds{ 10 });
    std::cout << "End program" << std::endl;
    return 0;
}

Висновок

На закінчення додаю архів із проектом.

Periodic.zip Periodic.zip

Рекомендовані статті на цю тему

По статті запитували0питання

1

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up