结合boost库实现的定时任务类

结合boost库实现的定时任务类

WorkEvent.h

#pragma once
#include <mutex>
#include <condition_variable>

namespace ASYN_WORK_NVR
{

    class CWorkEvent
    {
    public:
	   CWorkEvent();
	   ~CWorkEvent();
    public:
	   void SetEvent();
	   void WaitEvent();
	   void WaitEvent(const long long llTime);//ms,<0为一直等
	   void ResetEvent();
    private:
	   std::condition_variable m_conditionWake;
	   std::mutex m_mutexWake;
	   bool m_bWake;
    };

}

WorkEvent.cpp

#include <chrono>
#include "WorkEvent.h"

namespace ASYN_WORK_NVR
{

    CWorkEvent::CWorkEvent()
	   :m_bWake(false)
    {
    }

    CWorkEvent::~CWorkEvent()
    {
    }

    void CWorkEvent::SetEvent()
    {
	   std::unique_lock<std::mutex> lock(m_mutexWake);
	   if (!m_bWake)
	   {
		  m_bWake = true;
		  m_conditionWake.notify_one();
	   }
    }

    void CWorkEvent::WaitEvent()
    {
	   std::unique_lock<std::mutex> lock(m_mutexWake);
	   m_conditionWake.wait(lock, [&](){ return m_bWake; });
	   m_bWake = false;
    }

    void CWorkEvent::WaitEvent(const long long llTime)
    {
	   if (llTime < 0)
	   {
		  WaitEvent();
	   }
	   else
	   {
		  std::unique_lock<std::mutex> lock(m_mutexWake);
		  if (m_conditionWake.wait_for(lock, std::chrono::milliseconds(llTime), [&](){ return m_bWake; }))
		  {
			 m_bWake = false;
		  }
	   }
    }

    void CWorkEvent::ResetEvent()
    {
	   std::unique_lock<std::mutex> lock(m_mutexWake);
	   m_bWake = false;
    }

}

Timer.h

#pragma once
#include <thread>
#include <mutex>
#include <functional>
#include <chrono>
#include "boost/chrono.hpp" //需引用boost库的chrono.hpp
#include <vector>
#include "WorkEvent.h"

namespace ASYN_WORK_NVR
{

    class CTimer
    {
    public:
	   typedef std::function<void()> fn;
	   CTimer();
	   ~CTimer();
    public:
	   void Start(const unsigned long long gaps, const fn& f);
	   void Stop();
    private:
	   static void Init();
	   static void UnInit();
	   static void Run();
	   static bool GetMinGaps(unsigned long long& gaps);
    private:
	   static std::mutex m_mutexTimer;
	   static std::vector<CTimer*> m_vecTimer;

	   static std::thread* m_pThread;
	   static bool m_bExit;
	   static CWorkEvent m_event;

	   static unsigned long long m_ref;
	   static std::mutex m_mutexRef;
    private:
	   unsigned long long Check();
    private:
	   boost::chrono::time_point<boost::chrono::steady_clock> m_lastClock; //boost库的chrono.hpp
	   unsigned long long m_gaps;
	   fn m_f;
    };

}

Timer.cpp

#include "Timer.h"
#include <algorithm>

namespace ASYN_WORK_NVR
{

    std::mutex CTimer::m_mutexTimer;
    std::vector<CTimer*> CTimer::m_vecTimer;
    std::thread* CTimer::m_pThread = nullptr;
    bool CTimer::m_bExit = false;
    CWorkEvent CTimer::m_event;
    unsigned long long CTimer::m_ref = 0;
    std::mutex CTimer::m_mutexRef;

    CTimer::CTimer()
	   :m_lastClock(boost::chrono::steady_clock::now())
	   , m_gaps(1)
	   , m_f(nullptr)
    {
	   CTimer::Init();
    }

    CTimer::~CTimer()
    {
	   CTimer::UnInit();
    }

    void CTimer::Init()
    {
	   std::unique_lock<std::mutex> lock(m_mutexRef);
	   m_ref++;
	   if (1 == m_ref)
	   {
		  m_bExit = false;
		  m_pThread = new std::thread(CTimer::Run);
	   }
    }

    void CTimer::UnInit()
    {
	   std::unique_lock<std::mutex> lock(m_mutexRef);
	   m_ref--;
	   if (0 == m_ref)
	   {
		  m_bExit = true;
		  m_event.SetEvent();
		  if (m_pThread)
		  {
			 m_pThread->join();
			 delete m_pThread;
			 m_pThread = nullptr;
		  }
	   }
    }

    void CTimer::Run()
    {
	   while (!m_bExit)
	   {
		  unsigned long long llMinDelay = 0;
		  if (GetMinGaps(llMinDelay))
		  {
			 m_event.WaitEvent(llMinDelay);
		  }
		  else
		  {
			 m_event.WaitEvent();
		  }
	   }
    }

    bool CTimer::GetMinGaps(unsigned long long& gaps)
    {
	   std::unique_lock<std::mutex> lock(m_mutexTimer);
	   if (m_vecTimer.size() > 0)
	   {
		  gaps = m_vecTimer[0]->Check();
		  for (int i = 1; i < m_vecTimer.size(); i++)
		  {
			 auto tmp = m_vecTimer[i]->Check();
			 if (tmp < gaps)
			 {
				gaps = tmp;
			 }
		  }
		  return true;
	   }
	   return false;
    }

    void CTimer::Start(const unsigned long long gaps, const fn& f)
    {
	   m_gaps = gaps;
	   m_f = f;
	   m_lastClock = boost::chrono::steady_clock::now();
	   {
		  std::unique_lock<std::mutex> lock(m_mutexTimer);
		  m_vecTimer.push_back(this);
	   }
	   m_event.SetEvent();
    }

    void CTimer::Stop()
    {
	   std::unique_lock<std::mutex> lock(m_mutexTimer);
	   for (auto it = m_vecTimer.begin(); it != m_vecTimer.end(); it++)
	   {
		  if ((*it) == this)
		  {
			 m_vecTimer.erase(it);
			 return;
		  }
	   }
    }

    unsigned long long CTimer::Check()
    {
	   long long gaps = boost::chrono::duration_cast<boost::chrono::milliseconds>(boost::chrono::steady_clock::now() - m_lastClock).count();
	   if (gaps >= m_gaps)
	   {
		  if (m_f)
		  {
			 m_f();
		  }
		  m_lastClock = boost::chrono::steady_clock::now();
		  return m_gaps;
	   }
	   else
	   {
		  return (m_gaps - gaps);
	   }
    }

}

main.cpp

#include<memory>
#include<iostream>
#include<functional>
#include"Timer.h"

void Test()
{
	std::cout << "hello !!" << std::endl;
}

int main()
{	
 	std::shared_ptr<ASYN_WORK_NVR::CTimer>   pThreadTimerWorker
 	pThreadTimerWorker = std::make_shared<ASYN_WORK_NVR::CTimer>();
 	pThreadTimerWorker->Start(1000 * 60, std::bind(&Test));//1分钟执行一次Test

	if (pThreadTimerWorker) //停止定时任务
	{
		pThreadTimerWorker->Stop();
		pThreadTimerWorker = nullptr;
	}
	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用ROS和Boost实现串口通信的案例: 1. 在ROS工作空间中创建一个新的ROS包,例如“serial_communication”。 2. 在src目录下创建一个名为“serial_communication_node.cpp”的节点文件,并编写以下代码: ```c++ #include <ros/ros.h> #include <boost/asio.hpp> #include <boost/bind.hpp> #define SERIAL_PORT "/dev/ttyUSB0" // 串口号 #define BAUD_RATE 115200 // 波特率 class SerialCommunicationNode { public: SerialCommunicationNode() : io_service_(), serial_port_(io_service_) { // 打开串口 serial_port_.open(SERIAL_PORT); serial_port_.set_option(boost::asio::serial_port_base::baud_rate(BAUD_RATE)); // 创建定时器 timer_ = nh_.createTimer(ros::Duration(0.1), boost::bind(&SerialCommunicationNode::readSerialData, this)); } void readSerialData() { // 读取串口数据 boost::asio::async_read(serial_port_, boost::asio::buffer(buffer_), boost::asio::transfer_at_least(1), boost::bind(&SerialCommunicationNode::handleRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void handleRead(const boost::system::error_code& error, size_t bytes_transferred) { if (!error) { // 将读取到的串口数据发布为ROS消息 std_msgs::String msg; msg.data = std::string(buffer_.begin(), buffer_.begin() + bytes_transferred); serial_data_pub_.publish(msg); } } private: ros::NodeHandle nh_; ros::Publisher serial_data_pub_ = nh_.advertise<std_msgs::String>("serial_data", 1); ros::Timer timer_; boost::asio::io_service io_service_; boost::asio::serial_port serial_port_; std::vector<uint8_t> buffer_; }; int main(int argc, char** argv) { ros::init(argc, argv, "serial_communication_node"); SerialCommunicationNode node; ros::spin(); return 0; } ``` 3. 在CMakeLists.txt中添加以下内容: ``` find_package(Boost REQUIRED COMPONENTS system thread) include_directories(${Boost_INCLUDE_DIRS}) add_executable(serial_communication_node src/serial_communication_node.cpp) target_link_libraries(serial_communication_node ${Boost_LIBRARIES}) ``` 4. 构建并运行ROS节点: ``` catkin_make rosrun serial_communication serial_communication_node ``` 5. 在另一个终端中,使用roscore启动ROS核心,并使用rostopic命令检查是否已发布“serial_data”主题: ``` roscore rostopic list ``` 6. 将串口设备连接到计算机上,并使用minicom或其他串口工具发送数据。这将导致ROS节点将读取的数据作为ROS消息发布到“serial_data”主题中。 ``` minicom -b 115200 -D /dev/ttyUSB0 ``` 7. 最后,您可以使用rostopic echo命令来查看从串口读取的数据: ``` rostopic echo serial_data ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值