Пропоную написати невелику консольну програму, яка через рівні проміжки часу виконуватиме одне завдання.
Наприклад, програма запускається і робить 10 проб протягом 10 секунд, програма буде виводити інформацію про кількість зворотного відліку в консоль.
Програма працюватиме в такий спосіб.
Структура проекту
У проекті використовується система складання CMake, тому структура проекту буде наступною.
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;
- }
Висновок
На закінчення додаю архів із проектом.