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),实现优雅退出。
  • 多线程安全的设计确保在并发场景下,取消状态的修改和读取不会出现数据竞争或内存可见性问题。

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

相关推荐
火白学安全几秒前
《Python红队攻防零基础脚本编写:进阶篇(一)》
开发语言·python·安全·web安全·网络安全·系统安全
6***x5452 分钟前
C++在计算机视觉中的图像处理
c++·图像处理·计算机视觉·游戏引擎·logback·milvus
爱码小白3 分钟前
PyQt5 QTimer总结
开发语言·qt
fpcc5 分钟前
跟我学C++中级篇——内存访问违例
c++
A***27958 分钟前
Kotlin反射机制
android·开发语言·kotlin
E***q53913 分钟前
C++内存对齐优化
开发语言·c++
D_evil__14 分钟前
[C++高频精进] 文件IO:文件操作
c++
q***d17334 分钟前
Kotlin在后台服务中的框架
android·开发语言·kotlin
周杰伦fans42 分钟前
C# 中的 `Hashtable`
开发语言·c#
习习.y1 小时前
关于python中的面向对象
开发语言·python