I propose to write a small console program that will perform one task at regular intervals.
For example, the program starts and makes 10 samples within 10 seconds, while the program will display information about the number of the countdown in the console.
The program will work as follows.
Project structure
The project uses the CMake build system, so the project structure will be as follows..
CMakeLists.txt
Here is the standard CMake config for building the project.
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
Header file of the periodic task.
In the simplest case, to create a class of a periodic problem, we need:
- a trigger period
- object std::function to store the task
- variable bool to stop and start the task. In this example, we will not stop the task, but if we add run / stop methods, then it is quite possible to implement it.
- boost::thread - a thread without which this functionality cannot be implemented
#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
File with main function. When we create an object of a periodic task, we put the lambda function in it as the task, as the easiest way to indicate what work needs to be done.
#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; }
Coclusion
As a conclusion I attach the archive with the project.