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