Async++ 源码分析3---cancel.h

一、Async++ 代码目录结构

Async++ 项目的目录结构清晰,主要包含根目录下的配置文件、源代码目录、头文件目录以及示例代码目录,具体结构如下:

复制代码
asyncplusplus/
├── .gitignore               # Git 忽略文件配置
├── Async++Config.cmake.in   # CMake 配置模板文件
├── CMakeLists.txt           # CMake 构建脚本
├── LICENSE                  # 许可证文件(MIT 许可证)
├── README.md                # 项目说明文档
├── examples/                # 示例代码目录
│   └── gtk_scheduler.cpp    # GTK 调度器示例
├── src/                     # 源代码目录
│   ├── fifo_queue.h         # FIFO 队列实现
│   ├── internal.h           # 内部头文件(包含类型定义、宏等)
│   ├── scheduler.cpp        # 调度器实现
│   ├── singleton.h          # 单例模式实现
│   ├── task_wait_event.h    # 任务等待事件实现
│   ├── threadpool_scheduler.cpp  # 线程池调度器实现
│   └── work_steal_queue.h   # 工作窃取队列实现
└── include/                 # 头文件目录
    ├── async++.h            # 主头文件(对外提供统一接口)
    └── async++/             # 子模块头文件目录
        ├── aligned_alloc.h
        ├── cancel.h
        ├── continuation_vector.h
        ├── parallel_for.h
        ├── parallel_invoke.h
        ├── parallel_reduce.h
        ├── partitioner.h    # 分区器相关定义
        ├── range.h          # 范围(迭代器对)相关定义
        ├── ref_count.h
        ├── scheduler.h      # 调度器接口定义
        ├── scheduler_fwd.h
        ├── task.h           # 任务类定义
        ├── task_base.h      # 任务基类定义
        ├── traits.h
        └── when_all_any.h

二、cancel.h源码分析

2.1 源码
cpp 复制代码
// Copyright (c) 2015 Amanieu d'Antras
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#ifndef ASYNCXX_H_
# error "Do not include this header directly, include <async++.h> instead."
#endif

namespace async {

// Exception thrown by cancel_current_task()
struct LIBASYNC_EXPORT_EXCEPTION task_canceled {};

// A flag which can be used to request cancellation
class cancellation_token {
	std::atomic<bool> state;

public:
	cancellation_token()
		: state(false) {}

	// Non-copyable and non-movable
	cancellation_token(const cancellation_token&) = delete;
	cancellation_token& operator=(const cancellation_token&) = delete;

	bool is_canceled() const
	{
		bool s = state.load(std::memory_order_relaxed);
		if (s)
			std::atomic_thread_fence(std::memory_order_acquire);
		return s;
	}

	void cancel()
	{
		state.store(true, std::memory_order_release);
	}

	void reset()
	{
		state.store(false, std::memory_order_relaxed);
	}
};

// Interruption point, throws task_canceled if the specified token is set.
inline void interruption_point(const cancellation_token& token)
{
	if (token.is_canceled())
		LIBASYNC_THROW(task_canceled());
}

} // namespace async

这段代码是 Async++ 框架中关于任务取消机制 的核心实现,位于 async 命名空间,主要定义了任务取消相关的异常类型、取消令牌及中断点检查功能。以下是详细解析:

2.2. 核心组件说明

(1)task_canceled 异常
  • 这是一个空结构体,用于表示 "任务被取消" 的异常类型,通过 LIBASYNC_EXPORT_EXCEPTION 宏导出(确保跨模块可见)。
  • 当任务被取消时,框架会抛出该异常,供上层代码捕获并处理取消逻辑。
(2)cancellation_token 类(取消令牌)

一个用于标记 "是否请求取消任务" 的同步原语,核心功能是通过原子变量管理取消状态,供多线程安全访问。

核心成员
  • std::atomic<bool> state:原子变量,存储取消状态(false 未取消,true 已取消)。
关键方法
  • 构造函数 :初始化 statefalse(默认未取消)。
  • 禁用拷贝 / 移动 :通过 = delete 显式禁用拷贝构造和赋值,确保令牌唯一且状态不被意外复制。
  • is_canceled():检查是否已取消:
    • std::memory_order_relaxed 轻量加载 state(性能优先)。
    • 若状态为 true,插入 std::memory_order_acquire 内存栅栏,确保后续读取操作能看到取消前的内存状态(多线程同步)。
  • cancel():设置取消状态:
    • std::memory_order_release 存储 true,确保之前的写入操作对其他线程可见(同步语义)。
  • reset():重置取消状态为 false(用 std::memory_order_relaxed,适合单线程重置场景)。
(3)interruption_point 函数(中断点)
  • 功能:检查取消令牌状态,若已取消则抛出 task_canceled 异常。
  • 作用:作为任务执行过程中的 "检查点",让任务有机会响应取消请求。

2.3. 设计逻辑与多线程安全性

  • 原子操作与内存序 :通过 std::atomic 和内存栅栏(acquire/release)确保多线程环境下状态的一致性:
    • cancel()release 确保 "取消" 操作对其他线程可见。
    • is_canceled()acquire 确保读取到取消状态后,能正确同步后续操作。
  • 轻量设计:避免复杂锁机制,通过原子变量实现高效的状态查询和修改,适合高频调用场景。
  • 显式禁用拷贝:防止令牌被复制后,多个副本独立修改状态导致的逻辑混乱(确保取消操作的唯一性)。

2.4. 用法示例

以下是一个简单场景,展示如何使用这些组件实现任务取消:

cpp 复制代码
#include <async++.h>
#include <iostream>

// 模拟一个可被取消的任务
void long_running_task(async::cancellation_token& token) {
    try {
        for (int i = 0; i < 10; ++i) {
            // 每一步检查取消令牌(中断点)
            async::interruption_point(token);
            std::cout << "Task running: step " << i << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
        std::cout << "Task completed normally" << std::endl;
    } catch (const async::task_canceled&) {
        std::cout << "Task was canceled" << std::endl;
    }
}

int main() {
    async::cancellation_token token;

    // 启动异步任务
    auto task = async::spawn([&token] {
        long_running_task(token);
    });

    // 200ms 后取消任务
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    token.cancel();

    // 等待任务结束
    task.get();
    return 0;
}

输出预期

复制代码
Task running: step 0
Task running: step 1
Task was canceled

2.5. 核心作用

  • 为 Async++ 框架提供统一的任务取消机制,支持外部触发取消请求(通过 cancellation_token::cancel())。
  • 允许任务在执行过程中主动检查取消状态(通过 interruption_point),实现优雅退出。
  • 多线程安全的设计确保在并发场景下,取消状态的修改和读取不会出现数据竞争或内存可见性问题。

该机制是并发任务管理的重要组成部分,尤其适用于需要超时控制、用户主动终止等场景。

相关推荐
K_i1344 小时前
指针步长:C/C++内存操控的核心法则
java·开发语言
渡我白衣4 小时前
C++ :std::bind 还能用吗?它和 Lambda 有什么区别?
开发语言·c++·c++20
胖咕噜的稞达鸭4 小时前
算法入门:专题攻克主题一---双指针(1)移动零 复写零
c语言·开发语言·c++·算法
郝学胜-神的一滴4 小时前
Effective Python 第38条:简单的接口应该接受函数,而不是类的实例
开发语言·python·软件工程
一只小bit4 小时前
CMake 入门实战手册:从理解原理开始,打造高效 C/C++ 开发流程
c语言·开发语言·c++·cmake
青草地溪水旁4 小时前
设计模式(C++)详解——策略模式(1)
c++·设计模式·策略模式
secondyoung4 小时前
Markdown转换为Word:Pandoc模板使用指南
开发语言·经验分享·笔记·c#·编辑器·word·markdown
lly2024064 小时前
Django ORM - 聚合查询
开发语言
余衫马5 小时前
llama.cpp:本地大模型推理的高性能 C++ 框架
c++·人工智能·llm·llama·大模型部署