Asio学习:定时器

核心名词

  • io_context:事件循环/调度器,负责等待事件并执行回调(handler)。统一管理 IO 与定时器回调,便于扩展到网络模型。
  • handler(回调):事件就绪后被 run() 调用的函数/lambda。
  • async_wait:登记一次“到期后执行 handler”的异步操作;调用后立即返回(不阻塞)。
  • steady_timer:稳定定时器(不受系统时间调整影响)。
  • 多线程 run:多个线程同时调用 ioc.run(),同一时刻可能执行多个 handler。
  • strand:保证绑定到同一 strand 的 handler 不并发执行(串行化),但不保证固定线程。
  • work_guard:防止 run() 在暂时无任务时提前返回;reset() 后允许自然退出。

封装业务对象:Ticker

class Ticker : public std::enable_shared_from_this<Ticker> {
public:
  Ticker(asio::io_context &ico, int limit, std::function<void()> on_done)
      : strand_(asio::make_strand(ico)), timer_(strand_), limit_(limit),
        on_done_(on_done) {}

  void start() {
    // 开始第一次的tick
    schedule_next_tick();
  }
  
private:
  void schedule_next_tick() {
    timer_.expires_after(1s);
    timer_.async_wait(
        [self = shared_from_this()](const boost::system::error_code &ec) {
          if (ec) {
            std::cerr << "timer async wait error: " << ec.message() << "\n";
                    return;
          }
          self->tick();
    });
  }

  void tick() {
    ++count_;
    std::cout << "tick: " << count_
              << " (thread_id=" << std::this_thread::get_id() << ")\n";
    if (count_ >= limit_) {
      if (on_done_)
        on_done_();
      return;
    }
    // 安排下一次tick
    schedule_next_tick();
  }
  
private:
  asio::strand<asio::any_io_executor> strand_;
  asio::steady_timer timer_;
  int count_ = 0;
  int limit_;
  std::function<void()> on_done_;
};
  1. Ticker集成[std::](std::enable_shared_from_this,回调里面捕获 shared_from_this()

为什么这样做?

  • 异步回调可能在未来任意时刻触发
  • 捕获 shared_ptr 可以保证回调执行时对象仍然存在,避免悬空指针
  1. 内部绑定strand_绑定定时器调用
    • 多线程运行 io_context 会导致回调并发执行
    • strand 保证同一对象的回调串行化,避免数据竞争
    • 这样count_ 不需要加锁,更容易推理行为。

thread pool

strand (serial executor)

handler A

handler B

handler C

thread1: ioc.run()

thread2: ioc.run()

thread3: ioc.run()

io_context
ready handlers queue

  1. schedule_next_tick() 里 expires_after(1s) + async_wait,回调中再调用 schedule_next_tick()
    • 把“下一次调度”放在回调里,避免阻塞线程
    • 更容易与 io_context 的事件循环协作

保持事件循环存活(work_guard)

auto guard = asio::make_work_guard(ico);
auto on_done = [&guard]() { guard.reset(); };
  • 创建 executor_work_guard,任务完成后 reset()
    • 若没有未完成异步任务,io_context.run() 会立即返回
    • work_guard 让事件循环持续运行,直到我们主动停止
    • 完成时 reset(),确保线程池可以自然退出

线程池启动

// 线程池
std::vector<std::thread> pool;
pool.reserve(threads);
for (int i = 0; i < threads; ++i) {
  pool.emplace_back([&ico]() {
    ico.run();
  });
}
for (auto &t : pool) {
  t.join();
}

线程与并发模型

  • 线程池数量由 threads 控制
  • io_context 可以被多个线程并发运行
  • 绑定 strand_ 的回调串行执行,避免数据竞争

最小代码骨架

asio::io_context ioc;
auto guard = asio::make_work_guard(ioc);  // 可选但常用

// 1) 创建异步对象(timer/socket等)
// 2) 发起 async_* 操作,提供 handler(回调)
start_async_ops();

// 3) 一个或多个线程跑事件循环
std::thread t([&]{ ioc.run(); });
t.join();

定时器循环的通用写法:

void schedule() {
  timer.expires_after(1s);
  timer.async_wait([this](ec){
    if (!ec) { do_work(); schedule(); }
  });
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ht巷子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值