018 《folly/futures 权威指南:Future 和 Promise 深度解析与实战》
🌟🌟🌟本文案由Gemini 2.0 Flash Thinking Experimental 01-21创作,用来辅助学习知识。🌟🌟🌟
书籍大纲
▮▮▮▮ 1. chapter 1: 异步编程基础 (Fundamentals of Asynchronous Programming)
▮▮▮▮▮▮▮ 1.1 为什么需要异步编程 (Why Asynchronous Programming?)
▮▮▮▮▮▮▮ 1.2 同步与异步的概念 (Concepts of Synchronous and Asynchronous)
▮▮▮▮▮▮▮ 1.3 异步编程的优势与应用场景 (Advantages and Application Scenarios of Asynchronous Programming)
▮▮▮▮▮▮▮ 1.4 folly
库简介 (Introduction to folly
Library)
▮▮▮▮▮▮▮▮▮▮▮ 1.4.1 folly
的设计哲学与特点 (Design Philosophy and Features of folly
)
▮▮▮▮▮▮▮▮▮▮▮ 1.4.2 folly/futures
模块概述 (folly/futures
Module Overview)
▮▮▮▮▮▮▮▮▮▮▮ 1.4.3 编译与安装 folly
(folly
Compilation and Installation)
▮▮▮▮ 2. chapter 2: Future 和 Promise 核心概念 (Core Concepts of Future and Promise)
▮▮▮▮▮▮▮ 2.1 Future(未来值)的概念与作用 (Concept and Role of Future)
▮▮▮▮▮▮▮ 2.2 Promise(承诺)的概念与作用 (Concept and Role of Promise)
▮▮▮▮▮▮▮ 2.3 Future 和 Promise 的关系 (Relationship between Future and Promise)
▮▮▮▮▮▮▮ 2.4 Future<T>
的模板参数:类型系统 (Template Parameter of Future<T>
: Type System)
▮▮▮▮▮▮▮ 2.5 Promise<T>
的模板参数:类型系统 (Template Parameter of Promise<T>
: Type System)
▮▮▮▮ 3. chapter 3: Future 的基本操作 (Basic Operations of Future)
▮▮▮▮▮▮▮ 3.1 创建 Future 对象 (Creating Future Objects)
▮▮▮▮▮▮▮▮▮▮▮ 3.1.1 使用 Promise
创建 Future (Creating Future using Promise
)
▮▮▮▮▮▮▮▮▮▮▮ 3.1.2 使用 makeFuture()
函数 (Using makeFuture()
Function)
▮▮▮▮▮▮▮▮▮▮▮ 3.1.3 使用 Future::value()
和 Future::exception()
(Using Future::value()
and Future::exception()
)
▮▮▮▮▮▮▮ 3.2 获取 Future 的结果 (Getting the Result of a Future)
▮▮▮▮▮▮▮▮▮▮▮ 3.2.1 get()
方法:同步等待结果 (get()
Method: Synchronous Waiting for Result)
▮▮▮▮▮▮▮▮▮▮▮ 3.2.2 then()
方法:异步处理结果 (then()
Method: Asynchronous Result Handling)
▮▮▮▮▮▮▮ 3.3 Future 的状态 (States of Future)
▮▮▮▮▮▮▮▮▮▮▮ 3.3.1 isReady()
:检查 Future 是否完成 (isReady()
: Checking if Future is Ready)
▮▮▮▮▮▮▮▮▮▮▮ 3.3.2 isCancelled()
:检查 Future 是否被取消 (isCancelled()
: Checking if Future is Cancelled)
▮▮▮▮▮▮▮▮▮▮▮ 3.3.3 hasValue()
和 hasException()
:检查 Future 结果类型 (hasValue()
and hasException()
: Checking Future Result Type)
▮▮▮▮ 4. chapter 4: Promise 的基本操作 (Basic Operations of Promise)
▮▮▮▮▮▮▮ 4.1 创建 Promise 对象 (Creating Promise Objects)
▮▮▮▮▮▮▮ 4.2 设置 Promise 的结果 (Setting the Result of a Promise)
▮▮▮▮▮▮▮▮▮▮▮ 4.2.1 setValue()
:设置 Future 的值 (setValue()
: Setting the Value of Future)
▮▮▮▮▮▮▮▮▮▮▮ 4.2.2 setException()
:设置 Future 的异常 (setException()
: Setting the Exception of Future)
▮▮▮▮▮▮▮ 4.3 获取 Promise 关联的 Future (Getting the Future Associated with Promise)
▮▮▮▮▮▮▮ 4.4 Promise 的生命周期管理 (Lifecycle Management of Promise)
▮▮▮▮ 5. chapter 5: Future 的链式操作 (Chaining Operations of Future)
▮▮▮▮▮▮▮ 5.1 then()
:顺序执行异步操作 (then()
: Sequential Execution of Asynchronous Operations)
▮▮▮▮▮▮▮▮▮▮▮ 5.1.1 thenValue()
:处理 Future 的值 (thenValue()
: Handling the Value of Future)
▮▮▮▮▮▮▮▮▮▮▮ 5.1.2 thenError()
:处理 Future 的异常 (thenError()
: Handling the Exception of Future)
▮▮▮▮▮▮▮▮▮▮▮ 5.1.3 thenTry()
:处理 Future 的结果,包括值和异常 (thenTry()
: Handling Both Value and Exception of Future)
▮▮▮▮▮▮▮ 5.2 map()
:转换 Future 的值 (map()
: Transforming the Value of Future)
▮▮▮▮▮▮▮ 5.3 flatMap()
:扁平化 Future 的 Future (flatMap()
: Flattening Future of Future)
▮▮▮▮▮▮▮ 5.4 链式操作的错误处理 (Error Handling in Chaining Operations)
▮▮▮▮ 6. chapter 6: Future 的组合操作 (Combination Operations of Future)
▮▮▮▮▮▮▮ 6.1 collect()
:等待多个 Future 完成 (collect()
: Waiting for Multiple Futures to Complete)
▮▮▮▮▮▮▮ 6.2 select()
:选择最先完成的 Future (select()
: Selecting the First Completed Future)
▮▮▮▮▮▮▮ 6.3 race()
:竞争多个 Future,返回最先完成的结果 (race()
: Racing Multiple Futures, Returning the First Result)
▮▮▮▮▮▮▮ 6.4 andThen()
:在 Future 完成后执行另一个操作 (andThen()
: Executing Another Operation After Future Completion)
▮▮▮▮ 7. chapter 7: Future 的取消与超时 (Cancellation and Timeout of Future)
▮▮▮▮▮▮▮ 7.1 Future 的取消机制 (Cancellation Mechanism of Future)
▮▮▮▮▮▮▮▮▮▮▮ 7.1.1 Future::cancel()
:取消 Future (Future::cancel()
: Cancelling Future)
▮▮▮▮▮▮▮▮▮▮▮ 7.1.2 取消传播与协作 (Cancellation Propagation and Cooperation)
▮▮▮▮▮▮▮ 7.2 Future 的超时处理 (Timeout Handling of Future)
▮▮▮▮▮▮▮▮▮▮▮ 7.2.1 within()
:设置 Future 的超时时间 (within()
: Setting Timeout for Future)
▮▮▮▮▮▮▮▮▮▮▮ 7.2.2 超时异常处理 (Timeout Exception Handling)
▮▮▮▮ 8. chapter 8: Future 的异常处理 (Exception Handling of Future)
▮▮▮▮▮▮▮ 8.1 异常的传播与捕获 (Exception Propagation and Catching)
▮▮▮▮▮▮▮ 8.2 catch()
和 catchError()
:捕获特定类型的异常 (catch()
and catchError()
: Catching Specific Exception Types)
▮▮▮▮▮▮▮ 8.3 recover()
和 recoverWith()
:从异常中恢复 (recover()
and recoverWith()
: Recovering from Exception)
▮▮▮▮▮▮▮ 8.4 异常处理的最佳实践 (Best Practices for Exception Handling)
▮▮▮▮ 9. chapter 9: Future 与线程模型 (Future and Threading Model)
▮▮▮▮▮▮▮ 9.1 folly::Executor
接口 ( folly::Executor
Interface)
▮▮▮▮▮▮▮ 9.2 常见的 Executor
实现 (Common Executor
Implementations)
▮▮▮▮▮▮▮▮▮▮▮ 9.2.1 InlineExecutor
(内联执行器)
▮▮▮▮▮▮▮▮▮▮▮ 9.2.2 ThreadPoolExecutor
(线程池执行器)
▮▮▮▮▮▮▮▮▮▮▮ 9.2.3 IOThreadPoolExecutor
(IO 线程池执行器)
▮▮▮▮▮▮▮ 9.3 via()
:指定 Future 的执行上下文 (via()
: Specifying Execution Context for Future)
▮▮▮▮ 10. chapter 10: Future 的高级应用 (Advanced Applications of Future)
▮▮▮▮▮▮▮ 10.1 使用 Future 构建异步数据流 (Building Asynchronous Data Streams with Future)
▮▮▮▮▮▮▮ 10.2 使用 Future 实现并发控制 (Implementing Concurrency Control with Future)
▮▮▮▮▮▮▮ 10.3 Future 在微服务架构中的应用 (Application of Future in Microservice Architecture)
▮▮▮▮▮▮▮ 10.4 Future 与协程 (Future and Coroutines)
▮▮▮▮ 11. chapter 11: 实战案例分析 (Practical Case Studies)
▮▮▮▮▮▮▮ 11.1 案例一:异步文件 I/O 操作 (Case Study 1: Asynchronous File I/O Operations)
▮▮▮▮▮▮▮ 11.2 案例二:异步网络请求处理 (Case Study 2: Asynchronous Network Request Handling)
▮▮▮▮▮▮▮ 11.3 案例三:构建高并发的缓存系统 (Case Study 3: Building a High-Concurrency Cache System)
▮▮▮▮ 12. chapter 12: Future
API 全面解析 (Comprehensive API Analysis of Future
)
▮▮▮▮▮▮▮ 12.1 Future
类的方法详解 (Detailed Explanation of Future
Class Methods)
▮▮▮▮▮▮▮ 12.2 Future
相关的自由函数 (Free Functions Related to Future
)
▮▮▮▮ 13. chapter 13: Promise
API 全面解析 (Comprehensive API Analysis of Promise
)
▮▮▮▮▮▮▮ 13.1 Promise
类的方法详解 (Detailed Explanation of Promise
Class Methods)
▮▮▮▮ 14. chapter 14: 总结与展望 (Summary and Future Outlook)
▮▮▮▮▮▮▮ 14.1 folly/futures
的优势与局限性 (Advantages and Limitations of folly/futures
)
▮▮▮▮▮▮▮ 14.2 异步编程的未来发展趋势 (Future Development Trends of Asynchronous Programming)
1. chapter 1: 异步编程基础 (Fundamentals of Asynchronous Programming)
1.1 为什么需要异步编程 (Why Asynchronous Programming?)
在现代软件开发中,尤其是在构建高性能、高并发的应用程序时,异步编程 (Asynchronous Programming) 已经成为一项至关重要的技术。为了理解为什么我们需要异步编程,我们首先需要回顾传统的 同步编程 (Synchronous Programming) 模式及其局限性。
在同步编程模型中,任务是顺序执行 (Sequential Execution) 的。这意味着程序会按照代码的书写顺序,一步一步地执行每一条指令。当程序执行到某个可能会阻塞 (Blocking) 的操作时,例如等待 I/O (Input/Output) 完成(如读取文件、网络请求、数据库查询等),整个程序,或者至少是执行该操作的线程,会被暂停 (Suspended),直到操作完成。
考虑一个简单的例子:一个Web服务器需要处理多个客户端的请求。如果服务器使用同步编程模型,并且每个请求的处理都需要进行数据库查询,那么当服务器处理一个请求并等待数据库响应时,它就无法处理其他客户端的请求。这意味着服务器的资源利用率会非常低,并且在高并发场景下,响应速度会变得非常慢,甚至导致服务不可用。
1
// 同步文件读取示例 (Synchronous File Reading Example)
2
#include <iostream>
3
#include <fstream>
4
#include <string>
5
6
std::string readFile(const std::string& filename) {
7
std::ifstream file(filename);
8
if (!file.is_open()) {
9
throw std::runtime_error("Unable to open file");
10
}
11
std::string content;
12
std::string line;
13
while (std::getline(file, line)) {
14
content += line + "\n";
15
}
16
file.close();
17
return content;
18
}
19
20
int main() {
21
std::cout << "开始读取文件..." << std::endl; // Start reading file...
22
std::string fileContent = readFile("example.txt"); // 同步读取文件,程序在此处等待 (Synchronous file reading, program waits here)
23
std::cout << "文件内容:\n" << fileContent << std::endl; // File content: ...
24
std::cout << "文件读取完成,继续执行..." << std::endl; // File reading completed, continue execution...
25
return 0;
26
}
在上述代码中,readFile
函数使用同步方式读取文件。当程序调用 readFile
函数时,它会一直等待文件读取操作完成,然后才能继续执行后续的代码。如果文件很大,或者读取速度很慢,那么程序就会被阻塞很长时间。
同步编程的局限性在以下场景中尤为突出:
① I/O 密集型操作 (I/O-bound Operations):例如文件读写、网络请求、数据库查询等,这些操作通常需要等待外部资源,导致程序长时间阻塞。
② 需要高并发和低延迟的系统 (Systems Requiring High Concurrency and Low Latency):例如Web服务器、在线游戏服务器、实时数据处理系统等,同步阻塞会严重降低系统的吞吐量和响应速度。
③ 需要响应用户交互的应用程序 (Applications Requiring User Interaction):例如GUI程序,如果主线程被阻塞,会导致界面卡顿,用户体验非常差。
为了解决同步编程的这些问题,异步编程模型 (Asynchronous Programming Model) 应运而生。异步编程允许程序在发起一个可能阻塞的操作后,立即返回 (Return Immediately),而无需等待操作完成。程序可以继续执行其他的任务,当异步操作完成时,系统会通知程序,然后程序再来处理操作的结果。这种非阻塞 (Non-blocking) 的特性使得程序能够更有效地利用系统资源,提高并发性和响应速度。
1.2 同步与异步的概念 (Concepts of Synchronous and Asynchronous)
为了更清晰地理解异步编程,我们需要明确 同步 (Synchronous) 和 异步 (Asynchronous) 这两个核心概念。这两个概念描述的是程序执行和处理任务的方式,尤其是在处理可能耗时的操作时。
同步 (Synchronous)
同步操作是指调用者 (Caller) 发起一个操作后,必须等待 (Wait) 操作完成才能继续执行后续的代码。在同步模型中,任务是顺序执行 (Sequential Execution) 的,程序会按照代码的顺序一步一步执行,并且在执行到可能阻塞的操作时,会一直等待,直到操作返回结果。
可以把同步操作想象成你去餐厅点餐,你点完餐后,必须在餐桌旁等待服务员把菜端上来,你才能开始吃。在等待的过程中,你什么也做不了,只能等待。
特点:
⚝ 阻塞 (Blocking):调用者在等待操作完成时会被阻塞。
⚝ 顺序执行 (Sequential Execution):任务按照代码的顺序依次执行。
⚝ 简单直观 (Simple and Intuitive):代码逻辑清晰,易于理解和调试。
⚝ 资源利用率低 (Low Resource Utilization):在等待 I/O 操作时,线程会被空闲浪费。
⚝ 响应速度慢 (Slow Response Speed):在高并发场景下,容易出现性能瓶颈。
异步 (Asynchronous)
异步操作是指调用者 (Caller) 发起一个操作后,无需等待 (No Need to Wait) 操作完成,可以立即返回并继续执行后续的代码。当异步操作完成时,系统会通过某种机制(例如回调函数 (Callback Function)、事件通知 (Event Notification)、Promise/Future 等)通知调用者,然后调用者再来处理操作的结果。
可以把异步操作想象成你去餐厅点外卖,你点完餐后,不需要在餐厅等待,可以继续做自己的事情(例如工作、看书等)。当外卖送到时,外卖员会通知你,然后你再去取餐。在等待的过程中,你可以做其他的事情,提高了效率。
特点:
⚝ 非阻塞 (Non-blocking):调用者发起操作后立即返回,不会被阻塞。
⚝ 并发执行 (Concurrent Execution):可以同时发起多个异步操作,提高并发性。
⚝ 复杂性较高 (More Complex):代码逻辑相对复杂,需要处理回调、事件等异步机制。
⚝ 资源利用率高 (High Resource Utilization):在等待 I/O 操作时,线程可以继续执行其他任务。
⚝ 响应速度快 (Fast Response Speed):在高并发场景下,能够保持较高的吞吐量和响应速度。
同步与异步的对比 (Comparison of Synchronous and Asynchronous)
特性 (Feature) | 同步 (Synchronous) | 异步 (Asynchronous) |
---|---|---|
调用方式 (Calling) | 调用后等待结果返回 (Call and wait for result) | 调用后立即返回 (Call and return immediately) |
阻塞性 (Blocking) | 阻塞调用线程 (Blocking the calling thread) | 非阻塞调用线程 (Non-blocking the calling thread) |
执行顺序 (Execution Order) | 顺序执行 (Sequential execution) | 并发执行 (Concurrent execution) |
资源利用率 (Resource Utilization) | 较低 (Lower) | 较高 (Higher) |
响应速度 (Response Speed) | 较慢 (Slower) | 较快 (Faster) |
编程模型 (Programming Model) | 简单直观 (Simple and intuitive) | 相对复杂 (Relatively complex) |
适用场景 (Suitable Scenarios) | 任务执行时间短,并发不高 (Short tasks, low concurrency) | I/O 密集型,高并发,需要低延迟 (I/O-bound, high concurrency, low latency) |
理解同步和异步的关键在于是否需要等待操作完成。同步操作需要等待,而异步操作不需要等待。异步编程通过非阻塞的方式,提高了程序的并发性和资源利用率,尤其在处理 I/O 密集型任务时,能够显著提升性能。
1.3 异步编程的优势与应用场景 (Advantages and Application Scenarios of Asynchronous Programming)
异步编程的引入主要是为了解决同步编程在处理某些特定类型任务时的效率瓶颈。它带来了诸多优势,并在各种应用场景中发挥着关键作用。
异步编程的优势 (Advantages of Asynchronous Programming)
① 提高资源利用率 (Improved Resource Utilization):
在同步编程中,当程序执行 I/O 操作时,线程会被阻塞,等待 I/O 完成。这段等待时间,CPU 资源是被浪费的。而异步编程允许程序在发起 I/O 操作后立即返回,线程可以继续执行其他任务,从而提高了 CPU 和线程的利用率。尤其是在高并发场景下,异步编程能够更有效地利用有限的系统资源,提升系统的吞吐量。
② 提升系统响应速度 (Improved System Responsiveness):
对于需要快速响应的系统,例如Web服务器、GUI 应用程序等,同步阻塞会导致响应延迟。异步编程通过非阻塞的方式,使得系统能够更快地响应用户请求或其他事件。例如,在Web服务器中,使用异步处理请求,服务器可以在等待数据库查询或外部服务响应的同时,继续处理其他客户端的请求,从而降低了请求的平均响应时间。
③ 增强并发能力 (Enhanced Concurrency):
异步编程使得程序能够同时处理更多的任务。在同步编程中,处理并发任务通常需要创建大量的线程或进程,这会带来额外的资源开销和上下文切换的开销。而异步编程可以使用少量的线程(甚至单线程)来处理大量的并发任务,因为它在等待 I/O 操作时不会阻塞线程,从而提高了系统的并发能力。
④ 简化并发编程模型 (Simplified Concurrent Programming Model):
相比于传统的多线程或多进程并发编程,异步编程在某些场景下可以提供更简洁的并发模型。例如,使用 Promise/Future 或 async/await 等异步编程工具,可以更容易地组织和管理异步任务的执行流程,避免了传统多线程编程中常见的锁、条件变量等复杂的同步机制,降低了并发编程的复杂性。
异步编程的应用场景 (Application Scenarios of Asynchronous Programming)
① 网络编程 (Network Programming):
网络编程是异步编程最重要的应用场景之一。例如,Web服务器、客户端应用、网络爬虫等,都需要处理大量的并发网络请求。使用异步 I/O 可以构建高性能的网络应用,例如:
▮▮▮▮⚝ Web服务器 (Web Servers):Node.js、Nginx 等服务器都采用了异步非阻塞 I/O 模型,能够处理高并发的HTTP请求。
▮▮▮▮⚝ 客户端应用 (Client Applications):浏览器、移动应用等需要发起网络请求获取数据,异步请求可以避免界面卡顿,提升用户体验。
▮▮▮▮⚝ 即时通讯 (Instant Messaging):IM服务器需要处理大量的并发连接和消息收发,异步编程可以提高服务器的吞吐量和实时性。
② GUI 应用程序 (GUI Applications):
GUI 应用程序需要保持界面的流畅响应,避免因耗时操作而卡顿。例如,在GUI程序中执行文件操作、网络请求、复杂计算等任务时,应该使用异步方式,将耗时操作放在后台线程或异步任务中执行,避免阻塞主线程,保持界面的响应性。
③ 数据库操作 (Database Operations):
数据库操作通常是 I/O 密集型的,例如查询、写入等。使用异步数据库驱动可以提高数据库操作的并发性和效率。例如,异步ORM (Object-Relational Mapping) 框架、异步数据库连接池等,可以在高并发场景下提升数据库应用的性能。
④ 文件 I/O 操作 (File I/O Operations):
文件读写操作也可能是耗时的,尤其是在处理大文件时。异步文件 I/O 可以避免程序在等待文件操作完成时阻塞,提高程序的整体效率。例如,异步日志库、异步文件处理工具等。
⑤ 并发计算 (Concurrent Computation):
对于一些计算密集型任务,如果可以分解成多个独立的子任务并行执行,也可以使用异步编程来提高计算效率。例如,使用 Future 或 Task 等异步编程工具,可以将子任务提交到线程池或分布式系统并行执行,然后等待所有子任务完成,汇总结果。
总而言之,异步编程在 I/O 密集型、高并发、需要快速响应的场景下具有显著的优势。它能够提高资源利用率、提升系统响应速度、增强并发能力,并简化并发编程模型。随着软件系统越来越复杂,对性能和并发的要求越来越高,异步编程已经成为现代软件开发中不可或缺的技术。
1.4 folly
库简介 (Introduction to folly
Library)
folly
是 Facebook 开源的一个 C++ 库,全称是 "Facebook Open Source Library"。folly
包含了很多高性能、高可靠性的 C++ 组件,旨在解决实际工程中遇到的各种挑战,尤其是在构建大规模、高性能的服务器端应用方面。folly
库的设计目标是提供高效、灵活、可扩展的工具和组件,以支持 Facebook 内部的基础设施建设。
folly
库涵盖了广泛的领域,包括:
⚝ 数据结构 (Data Structures):例如 FBVector
(针对特定场景优化的 vector)、F14ValueMap
(高性能哈希表) 等。
⚝ 算法 (Algorithms):例如 sorted_vector
(有序向量)、small_vector
(针对小尺寸优化的 vector) 等。
⚝ 并发与异步编程 (Concurrency and Asynchronous Programming):例如 Future/Promise
、Executor
、EventCount
等。
⚝ 网络编程 (Network Programming):例如 Socket
、IOBuf
(高效的 I/O buffer)、AsyncSocket
(异步 socket) 等。
⚝ 时间与定时器 (Time and Timers):例如 HHWheelTimer
(分层时间轮定时器)、EventBase
(事件循环) 等。
⚝ 字符串处理 (String Processing):例如 fbstring
(针对特定场景优化的 string)、StringPiece
(字符串视图) 等。
⚝ 配置与选项 (Configuration and Options):例如 CommandLine
(命令行参数解析)、Flags
(配置标志) 等。
⚝ 实用工具 (Utilities):例如 Singleton
(单例模式)、Optional
(可选值)、Expected
(可能包含值或错误的结果) 等。
folly
库的设计哲学和特点使其成为构建高性能 C++ 应用的强大工具。接下来,我们将深入了解 folly
的设计哲学与特点,以及 folly/futures
模块。
1.4.1 folly
的设计哲学与特点 (Design Philosophy and Features of folly
)
folly
库的设计哲学和特点主要体现在以下几个方面:
① 性能至上 (Performance First):
folly
的首要设计目标是性能。folly
中的组件和工具都经过精心的优化,旨在提供尽可能高的性能。例如,folly
提供了各种高性能的数据结构和算法,以及高效的 I/O 和并发编程工具。folly
的设计者们深入理解硬件特性和操作系统底层机制,通过精细的优化,使得 folly
在性能方面表现出色。
② 实用性与工程性 (Practicality and Engineering Focus):
folly
并非一个纯粹的学术研究项目,而是一个源于实际工程需求的库。folly
中的组件和工具都是为了解决 Facebook 在构建大规模系统时遇到的实际问题而开发的。因此,folly
非常注重实用性和工程性,提供的功能都是经过实际验证和广泛应用的。
③ 模块化与可扩展性 (Modularity and Extensibility):
folly
采用模块化的设计,各个组件之间相对独立,可以根据需要选择性地使用。这种模块化设计使得 folly
具有良好的可扩展性,可以方便地添加新的组件和功能。同时,folly
的代码结构清晰,易于理解和维护,方便开发者进行二次开发和定制。
④ 现代 C++ 特性 (Modern C++ Features):
folly
充分利用了现代 C++ 的特性,例如 模板 (Templates)、RAII (Resource Acquisition Is Initialization)、移动语义 (Move Semantics)、Lambda 表达式 (Lambda Expressions) 等。这使得 folly
的代码更加简洁、高效、安全。同时,使用现代 C++ 特性也使得 folly
能够更好地与其他现代 C++ 库和工具集成。
⑤ 开源与社区 (Open Source and Community):
folly
是一个开源项目,遵循 Apache 2.0 许可证 (Apache License 2.0)。开源使得 folly
能够受益于更广泛的社区贡献,同时也促进了 folly
的发展和完善。folly
拥有活跃的社区,开发者可以通过 GitHub 提交 issue 和 pull request,参与到 folly
的开发中。
folly
的主要特点总结:
⚝ 高性能 (High Performance):针对性能进行了深度优化。
⚝ 实用性 (Practical):解决实际工程问题,经过实践验证。
⚝ 模块化 (Modular):组件独立,可选择性使用。
⚝ 可扩展性 (Extensible):易于扩展和定制。
⚝ 现代 C++ (Modern C++):充分利用现代 C++ 特性。
⚝ 开源 (Open Source):开放源代码,社区驱动。
1.4.2 folly/futures
模块概述 (folly/futures
Module Overview)
folly/futures
模块是 folly
库中专门用于 异步编程 (Asynchronous Programming) 的模块。它提供了一套强大的工具,用于处理异步操作、管理并发任务、以及构建响应式系统。folly/futures
模块的核心概念是 Future
(未来值) 和 Promise
(承诺),它们是实现异步编程的关键抽象。
folly/futures
模块的主要组件和功能包括:
① Future<T>
(未来值):
Future<T>
代表一个异步操作的结果,这个结果可能在将来某个时刻才能得到。Future
对象本身并不包含结果,而是提供了一种机制,允许你在结果可用时异步地获取它。Future
可以表示一个值、一个异常,或者操作尚未完成。folly::Future
提供了丰富的操作,例如链式调用 (then
, map
, flatMap
)、组合操作 (collect
, select
, race
)、错误处理 (catch
, recover
)、取消 (cancel
)、超时 (within
) 等,使得异步编程更加灵活和强大。
② Promise<T>
(承诺):
Promise<T>
是用于设置 Future<T>
的结果的。Promise
和 Future
通常是成对出现的。Promise
对象负责设置 Future
对象的结果(值或异常),而 Future
对象则用于获取这个结果。Promise
提供 setValue()
和 setException()
方法来设置 Future
的结果,以及 getFuture()
方法来获取与之关联的 Future
对象。
③ Executor
(执行器):
folly::Executor
是一个抽象接口,用于执行异步任务。Executor
定义了任务的提交和执行策略,例如在哪个线程或线程池中执行任务。folly/futures
模块提供了多种 Executor
的实现,例如 InlineExecutor
(内联执行器)、ThreadPoolExecutor
(线程池执行器)、IOThreadPoolExecutor
(I/O 线程池执行器) 等,可以根据不同的场景选择合适的执行器。
④ 异步操作的组合与控制 (Combination and Control of Asynchronous Operations):
folly/futures
提供了丰富的操作,用于组合和控制多个异步操作的执行流程。例如:
▮▮▮▮⚝ 链式操作 (Chaining Operations):使用 then
、map
、flatMap
等方法,可以将多个异步操作串联起来,形成一个异步操作链。
▮▮▮▮⚝ 组合操作 (Combination Operations):使用 collect
、select
、race
等方法,可以将多个独立的异步操作组合成一个更复杂的异步操作。
▮▮▮▮⚝ 错误处理 (Error Handling):使用 catch
、recover
等方法,可以处理异步操作中可能出现的异常。
▮▮▮▮⚝ 取消与超时 (Cancellation and Timeout):使用 cancel
和 within
等方法,可以取消异步操作或设置超时时间。
⑤ 与 folly::EventBase
集成 (Integration with folly::EventBase
):
folly/futures
模块与 folly::EventBase
(事件循环) 紧密集成。EventBase
是 folly
中用于处理 I/O 事件和定时器的核心组件。folly/futures
可以与 EventBase
协同工作,实现高效的异步 I/O 操作和事件驱动编程。
folly/futures
模块的核心价值:
⚝ 简化异步编程 (Simplified Asynchronous Programming):通过 Future
和 Promise
等抽象,降低了异步编程的复杂性。
⚝ 提高代码可读性和可维护性 (Improved Code Readability and Maintainability):链式操作和组合操作使得异步代码更加清晰和易于理解。
⚝ 增强并发能力 (Enhanced Concurrency):通过非阻塞的异步操作和灵活的执行器,提高了系统的并发能力。
⚝ 提供丰富的异步编程工具 (Rich Set of Asynchronous Programming Tools):提供了各种操作和组件,满足不同的异步编程需求。
folly/futures
模块是构建高性能、高并发 C++ 应用的强大工具,尤其适用于处理 I/O 密集型任务和构建响应式系统。本书将深入探讨 folly/futures
模块的各个方面,帮助读者掌握其核心概念、基本操作、高级应用和 API 细节。
1.4.3 编译与安装 folly
(folly
Compilation and Installation)
在开始使用 folly/futures
之前,我们需要先编译 (Compile) 和 安装 (Install) folly
库。folly
的编译和安装过程相对复杂,因为它依赖于许多其他的库和工具。以下是编译和安装 folly
的基本步骤和注意事项。
前提条件 (Prerequisites)
在编译 folly
之前,需要确保系统满足以下前提条件:
① 操作系统 (Operating System):
folly
主要在 Linux 和 macOS 系统上进行开发和测试。Windows 系统上的支持可能有限,需要使用特定的编译环境(例如 Cygwin 或 WSL (Windows Subsystem for Linux))。
② C++ 编译器 (C++ Compiler):
folly
需要支持 C++17 标准的编译器。推荐使用 GCC (GNU Compiler Collection) 7 或更高版本,或者 Clang 5 或更高版本。
③ CMake (Cross-platform Make):
folly
使用 CMake 作为构建系统。需要安装 CMake 3.12 或更高版本。
④ Python (Python):
folly
的构建脚本和一些工具使用 Python 3。需要安装 Python 3.6 或更高版本。
⑤ 依赖库 (Dependencies):
folly
依赖于许多其他的开源库,包括:
▮▮▮▮⚝ Boost (>= 1.60):一个广泛使用的 C++ 库集合。
▮▮▮▮⚝ Double-conversion:快速精确的 double 和 string 转换库。
▮▮▮▮⚝ Gflags:命令行参数解析库。
▮▮▮▮⚝ Glog:Google logging 库。
▮▮▮▮⚝ Libevent (>= 2.1):事件通知库。
▮▮▮▮⚝ Libsodium:现代密码学库。
▮▮▮▮⚝ LZ4:快速压缩算法库。
▮▮▮▮⚝ OpenSSL:安全套接字层协议库。
▮▮▮▮⚝ Snappy:快速压缩/解压缩库。
▮▮▮▮⚝ Zlib:通用压缩库。
▮▮▮▮⚝ Zstd:Zstandard 压缩算法库。
这些依赖库通常可以通过系统的包管理器进行安装,例如 apt-get
(Debian/Ubuntu)、yum
(CentOS/RHEL)、brew
(macOS) 等。
编译步骤 (Compilation Steps)
以下是在 Linux 或 macOS 系统上编译 folly
的基本步骤:
① 获取 folly
源代码 (Get folly
Source Code):
可以通过 Git 从 GitHub 仓库克隆 folly
的源代码:
1
git clone https://github.com/facebook/folly.git
2
cd folly
② 创建构建目录 (Create Build Directory):
建议在 folly
源代码目录外创建一个独立的构建目录,例如 build
:
1
mkdir build
2
cd build
③ 运行 CMake 配置 (Run CMake Configuration):
在构建目录中运行 CMake 配置命令,指定 folly
源代码的路径:
1
cmake ..
CMake 会自动检测系统环境和依赖库,并生成 Makefile 或其他构建文件。
可选的 CMake 配置选项 (Optional CMake Configuration Options):
▮▮▮▮⚝ -DCMAKE_INSTALL_PREFIX=<安装路径>
:指定 folly
的安装路径,默认为 /usr/local
。
▮▮▮▮⚝ -DCMAKE_BUILD_TYPE=<构建类型>
:指定构建类型,例如 Debug
、Release
、RelWithDebInfo
等。默认为 Debug
。
▮▮▮▮⚝ -DFOLLY_USE_SYSTEM_GFLAGS=ON
:使用系统安装的 Gflags 库,而不是 folly
自带的版本。
▮▮▮▮⚝ -DFOLLY_USE_SYSTEM_GLOG=ON
:使用系统安装的 Glog 库,而不是 folly
自带的版本。
▮▮▮▮⚝ 更多配置选项可以参考 folly
的 CMakeLists.txt 文件和官方文档。
④ 编译 folly
(Compile folly
):
运行 make
命令开始编译 folly
:
1
make -j$(nproc) # 使用多核并行编译,加快编译速度
-j$(nproc)
选项表示使用所有可用的 CPU 核心进行并行编译。
⑤ 安装 folly
(Install folly
):
编译完成后,运行 make install
命令将 folly
安装到指定的安装路径(默认为 /usr/local
):
1
sudo make install
需要使用 sudo
权限进行安装,因为默认安装路径 /usr/local
通常需要管理员权限。
验证安装 (Verification of Installation)
安装完成后,可以通过以下方式验证 folly
是否安装成功:
① 检查头文件 (Check Header Files):
检查在安装路径的 include
目录下是否存在 folly
目录,以及 folly/futures/Future.h
和 folly/futures/Promise.h
等头文件。例如,如果安装路径为 /usr/local
,则头文件路径应为 /usr/local/include/folly/futures/Future.h
。
② 检查库文件 (Check Library Files):
检查在安装路径的 lib
目录下是否存在 folly
的库文件,例如 libfolly.a
(静态库) 或 libfolly.so
(动态库)。例如,如果安装路径为 /usr/local
,则库文件路径应为 /usr/local/lib/libfolly.so
或 /usr/local/lib/libfolly.a
。
③ 编译示例代码 (Compile Example Code):
编写一个简单的 C++ 程序,包含 folly/futures/Future.h
头文件,并使用 folly::Future
类,尝试编译并运行,看是否能够正常编译和链接。
1
// example.cpp
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> f = folly::makeFuture(42);
7
std::cout << "Future value: " << f.get() << std::endl;
8
return 0;
9
}
使用 g++ 编译示例代码,并链接 folly
库:
1
g++ example.cpp -o example -lfolly -pthread
2
./example
如果程序能够成功编译和运行,并输出 "Future value: 42",则说明 folly
库安装成功。
注意事项 (Precautions)
⚝ 依赖库版本 (Dependency Library Versions):确保系统中安装的依赖库版本符合 folly
的要求。版本不兼容可能会导致编译错误或运行时错误。
⚝ 编译选项 (Compilation Options):根据实际需求和系统环境,可以调整 CMake 的配置选项,例如指定安装路径、构建类型、是否使用系统库等。
⚝ 错误处理 (Error Handling):如果在编译或安装过程中遇到错误,仔细查看错误信息,检查是否缺少依赖库、CMake 版本是否过低、编译器是否支持 C++17 等。可以参考 folly
的官方文档和 GitHub 仓库的 issue 列表,查找解决方案。
通过以上步骤,你就可以成功地编译和安装 folly
库,并开始使用 folly/futures
模块进行异步编程开发。在后续的章节中,我们将深入学习 folly/futures
的核心概念和 API,并通过实战案例来掌握异步编程的技巧。
END_OF_CHAPTER
2. chapter 2: Future 和 Promise 核心概念 (Core Concepts of Future and Promise)
2.1 Future(未来值)的概念与作用 (Concept and Role of Future)
在异步编程的世界中,Future(未来值)
扮演着至关重要的角色。它就像一个占位符 ⏳,代表着一个尚未完成的操作的结果。这个结果可能在将来某个时刻可用,也可能永远不会可用(例如,操作失败)。Future
允许我们在不知道结果何时到来的情况下,继续执行程序的其他部分,从而实现非阻塞和高效的并发。
概念 (Concept):
Future
本质上是一个只读的、代表未来结果的对象。你可以把它想象成一张期票,承诺在未来某个时间点给你一个值。这个值可以是任何类型的数据,例如整数、字符串、复杂对象,甚至可以表示操作的完成(void
)。
作用 (Role):
① 异步操作的返回值 (Return Value of Asynchronous Operations): Future
最主要的作用是作为异步操作的返回值。当一个函数启动一个异步任务时,它不会立即返回最终结果,而是返回一个 Future
对象。这个 Future
对象代表着异步任务的执行结果。
② 解耦调用者和被调用者 (Decoupling Caller and Callee): Future
将异步操作的发起者(调用者)和结果的提供者(被调用者)解耦。调用者无需等待异步操作完成即可继续执行,而结果将在 Future
对象中“未来”可用。
③ 链式操作和组合操作的基础 (Foundation for Chaining and Combination Operations): Future
提供了一系列强大的操作,例如 then()
、map()
、flatMap()
、collect()
等,允许我们将多个异步操作链接起来,或者将多个 Future
组合成更复杂的异步流程。这使得异步编程更加灵活和强大。
④ 错误处理 (Error Handling): Future
不仅可以表示成功的结果,还可以表示操作失败或发生异常的情况。通过 Future
的错误处理机制,我们可以优雅地处理异步操作中可能出现的错误,保证程序的健壮性。
生活中的类比 (Analogy in Life):
我们可以将 Future
比作餐厅的点餐小票。当你点餐后,服务员会给你一张小票,上面记录了你的订单。这张小票就相当于 Future
,它代表着你未来将获得的餐点(结果)。你拿到小票后,不需要站在前台等待餐点做好,可以先回到座位上做其他事情(继续执行程序)。当餐点准备好后,餐厅会叫号,你就可以凭小票去领取餐点(获取 Future
的结果)。
1
#include <folly/futures/Future.h>
2
#include <folly/futures/Promise.h>
3
#include <iostream>
4
5
using namespace folly;
6
7
Future<int> asyncTask() {
8
Promise<int> promise;
9
// 模拟异步操作,例如网络请求或耗时计算
10
std::thread([p = std::move(promise)]() {
11
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时 2 秒
12
p.setValue(42); // 设置 Future 的结果为 42
13
}).detach();
14
return promise.getFuture(); // 返回与 Promise 关联的 Future
15
}
16
17
int main() {
18
Future<int> futureResult = asyncTask(); // 发起异步任务,获得 Future
19
std::cout << "异步任务已发起,等待结果..." << std::endl;
20
21
// 在结果准备好之前,可以执行其他操作
22
std::cout << "执行其他操作..." << std::endl;
23
24
// 获取 Future 的结果 (同步等待,仅为演示目的,实际应用中应避免在主线程同步等待)
25
int result = futureResult.get();
26
std::cout << "异步任务结果: " << result << std::endl;
27
28
return 0;
29
}
在这个例子中,asyncTask()
函数返回一个 Future<int>
对象,代表着异步任务的结果。main()
函数获得 Future
后,可以继续执行其他操作,而无需阻塞等待异步任务完成。最终通过 futureResult.get()
获取异步任务的结果。
2.2 Promise(承诺)的概念与作用 (Concept and Role of Promise)
与 Future
相辅相成的是 Promise(承诺)
。如果 Future
是代表未来结果的期票,那么 Promise
就是兑现这张期票的机制 🔑。Promise
允许设置(或“兑现”)与之关联的 Future
的结果,无论是成功的值还是失败的异常。
概念 (Concept):
Promise
是一个可写的对象,它允许单次设置与之关联的 Future
的结果。一旦 Promise
设置了结果(无论是值还是异常),与之关联的 Future
的状态就会变为 “已完成”,并且结果将不可更改。每个 Promise
只能关联一个 Future
,并且只能被“兑现”一次。
作用 (Role):
① 设置 Future 的结果 (Setting the Result of Future): Promise
最核心的作用是设置与之关联的 Future
的结果。通过 Promise
,异步操作的执行者可以在操作完成后,将结果(成功值或异常)传递给 Future
,从而完成 Future
的“兑现”。
② 连接异步操作的生产者和消费者 (Connecting Producer and Consumer of Asynchronous Operations): Promise
充当了异步操作的生产者和 Future
的消费者之间的桥梁。生产者通过 Promise
设置结果,消费者通过 Future
获取结果,实现了异步操作结果的传递。
③ 控制 Future 的生命周期 (Controlling the Lifecycle of Future): Promise
掌握着与之关联的 Future
的完成权。只有通过 Promise
设置结果,Future
才能进入 “已完成” 状态。这使得 Promise
成为控制 Future
生命周期的重要工具。
④ 异常处理的桥梁 (Bridge for Exception Handling): Promise
不仅可以设置成功的值,还可以设置异常。这使得 Promise
成为异步操作异常处理的关键环节。通过 Promise
设置异常,可以将异步操作中发生的错误传递给 Future
,并最终传递给 Future
的消费者进行处理。
生活中的类比 (Analogy in Life):
继续使用餐厅的例子,Promise
可以比作餐厅的厨房 👨🍳。厨房接收到点餐小票(Future
)后,开始准备餐点。当餐点准备好后,厨房会兑现这张小票,将餐点(结果)交给顾客。厨房负责设置最终的结果(餐点),而顾客通过小票(Future
)来获取这个结果。
1
#include <folly/futures/Future.h>
2
#include <folly/futures/Promise.h>
3
#include <iostream>
4
#include <stdexcept>
5
6
using namespace folly;
7
8
Future<std::string> fetchDataFromNetwork() {
9
Promise<std::string> promise;
10
std::thread([p = std::move(promise)]() {
11
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟网络请求延迟
12
bool success = true; // 假设网络请求成功
13
if (success) {
14
p.setValue("Data from network"); // 设置成功值
15
} else {
16
p.setException(std::runtime_error("Network request failed")); // 设置异常
17
}
18
}).detach();
19
return promise.getFuture();
20
}
21
22
int main() {
23
Future<std::string> dataFuture = fetchDataFromNetwork();
24
25
dataFuture.thenValue([](const std::string& data) {
26
std::cout << "成功获取数据: " << data << std::endl;
27
}).thenError([](const std::runtime_error& error) {
28
std::cerr << "获取数据失败: " << error.what() << std::endl;
29
});
30
31
// ... 执行其他操作 ...
32
33
return 0;
34
}
在这个例子中,fetchDataFromNetwork()
函数创建了一个 Promise<std::string>
,并在一个新线程中模拟网络请求。根据请求结果,Promise
被设置为成功值或异常。main()
函数通过 Future
的 thenValue()
和 thenError()
方法处理成功和失败的情况。
2.3 Future 和 Promise 的关系 (Relationship between Future and Promise)
Future
和 Promise
是异步编程中一对紧密关联、相辅相成的概念。它们共同构成了一种强大的机制,用于处理异步操作的结果。理解它们之间的关系是掌握 folly/futures
库的关键。
核心关系 (Core Relationship):
① Promise 创建 Future (Promise Creates Future): Promise
对象是 Future
对象的创建者。每个 Promise
对象在创建时,都会同时创建一个与之关联的 Future
对象。可以通过 promise.getFuture()
方法获取这个关联的 Future
。
② Promise 设置 Future 的结果 (Promise Sets the Result of Future): Promise
负责设置与之关联的 Future
的最终结果。通过 promise.setValue(value)
可以设置 Future
的成功值,通过 promise.setException(exception)
可以设置 Future
的异常。
③ Future 获取 Promise 设置的结果 (Future Gets the Result Set by Promise): Future
对象是只读的,它不能直接设置结果,但可以获取与之关联的 Promise
设置的结果。当 Promise
设置了结果后,Future
的状态变为 “已完成”,并且可以通过 get()
、then()
等方法获取结果。
④ 一对一关系 (One-to-One Relationship): 一个 Promise
对象只能关联一个 Future
对象,反之亦然。这种一对一的关系保证了异步操作结果的唯一性和确定性。
⑤ 生产者-消费者模式 (Producer-Consumer Pattern): Promise
扮演着生产者的角色,它负责生成异步操作的结果并“承诺”在未来提供。Future
扮演着消费者的角色,它等待 Promise
兑现承诺,并最终获取结果。
图示 (Diagram):
\[ \text{Promise} \xrightarrow{\text{创建 (Creates)}} \text{Future} \]
\[ \text{Promise} \xrightarrow{\text{设置结果 (Sets Result)}} \text{Future} \]
\[ \text{Future} \xrightarrow{\text{获取结果 (Gets Result)}} \text{Consumer (消费者)} \]
总结 (Summary):
Future
和 Promise
共同构成了一个异步结果传递管道。Promise
负责写入结果到管道中,Future
负责从管道中读取结果。它们协同工作,实现了异步操作结果的生产和消费,是构建异步程序的基石。
1
#include <folly/futures/Future.h>
2
#include <folly/futures/Promise.h>
3
#include <iostream>
4
5
using namespace folly;
6
7
int main() {
8
Promise<int> promise; // 创建 Promise 对象
9
Future<int> future = promise.getFuture(); // 获取与 Promise 关联的 Future
10
11
std::thread([p = std::move(promise)]() {
12
std::this_thread::sleep_for(std::chrono::seconds(1));
13
p.setValue(100); // Promise 设置 Future 的值
14
}).detach();
15
16
future.thenValue([](int value) { // Future 获取 Promise 设置的值
17
std::cout << "Future received value: " << value << std::endl;
18
});
19
20
// ... 执行其他操作 ...
21
22
return 0;
23
}
在这个例子中,Promise
和 Future
被创建并关联。Promise
在后台线程中设置了值 100
,而 Future
通过 thenValue()
方法异步地接收并处理了这个值,展示了 Future
和 Promise
协同工作的基本模式。
2.4 Future<T>
的模板参数:类型系统 (Template Parameter of Future<T>
: Type System)
folly::Future<T>
是一个模板类,其中的模板参数 T
定义了 Future
对象所代表的异步操作结果的类型。类型系统在 Future
的使用中扮演着至关重要的角色,它确保了类型安全,并为异步编程提供了强大的表达能力。
模板参数 T
的含义 (Meaning of Template Parameter T
):
T
可以是任何 C++ 类型,包括:
① 基本数据类型 (Primitive Types): 例如 int
, bool
, float
, double
等。当异步操作的结果是一个基本数据类型时,可以使用 Future<int>
, Future<bool>
等。
② 自定义类和结构体 (Custom Classes and Structs): T
可以是用户自定义的类或结构体。这使得 Future
可以表示复杂对象的异步计算结果。例如,如果有一个异步函数返回一个 User
对象,可以使用 Future<User>
.
③ void
类型 (Void Type): Future<void>
表示一个不返回任何具体值的异步操作。它只表示异步操作的完成。例如,一个异步写入文件的操作可能返回 Future<void>
.
④ 智能指针 (Smart Pointers): 例如 std::shared_ptr<T>
, std::unique_ptr<T>
. 使用智能指针作为 Future
的模板参数可以方便地管理异步操作返回的动态分配的对象的生命周期。例如 Future<std::shared_ptr<Data>>
.
⑤ 其他 Future
类型 (Other Future Types): Future
甚至可以嵌套,例如 Future<Future<int>>
. 这通常出现在需要处理返回 Future
的异步操作的场景中,可以通过 flatMap()
等操作进行“扁平化”处理。
类型安全 (Type Safety):
Future<T>
的类型系统提供了编译时类型检查,确保了异步操作结果的类型安全。例如,如果一个函数声明返回 Future<int>
,那么编译器会确保你不会尝试将一个字符串类型的结果设置到这个 Future
中,从而避免了潜在的类型错误。
类型推导 (Type Deduction):
在很多情况下,C++ 的模板类型推导机制可以自动推导出 Future<T>
的模板参数 T
,从而简化代码编写。例如,在使用 makeFuture()
函数创建 Future
时,通常不需要显式指定模板参数,编译器会根据传入的值自动推导类型。
示例 (Examples):
1
#include <folly/futures/Future.h>
2
#include <folly/futures/Promise.h>
3
#include <iostream>
4
#include <string>
5
#include <memory>
6
7
using namespace folly;
8
9
Future<int> asyncCalculateSum() {
10
Promise<int> promise;
11
std::thread([p = std::move(promise)]() {
12
std::this_thread::sleep_for(std::chrono::seconds(1));
13
p.setValue(10 + 20); // 返回 int 类型的结果
14
}).detach();
15
return promise.getFuture();
16
}
17
18
Future<std::string> asyncFetchUserName(int userId) {
19
Promise<std::string> promise;
20
std::thread([p = std::move(promise), userId]() {
21
std::this_thread::sleep_for(std::chrono::seconds(1));
22
p.setValue("User_" + std::to_string(userId)); // 返回 std::string 类型的结果
23
}).detach();
24
return promise.getFuture();
25
}
26
27
Future<void> asyncLogEvent() {
28
Promise<void> promise;
29
std::thread([p = std::move(promise)]() {
30
std::this_thread::sleep_for(std::chrono::seconds(1));
31
std::cout << "Event logged asynchronously" << std::endl;
32
p.setValue(); // 返回 void 类型,表示操作完成
33
}).detach();
34
return promise.getFuture();
35
}
36
37
struct Data {
38
int value;
39
std::string message;
40
};
41
42
Future<std::shared_ptr<Data>> asyncCreateData() {
43
Promise<std::shared_ptr<Data>> promise;
44
std::thread([p = std::move(promise)]() {
45
std::this_thread::sleep_for(std::chrono::seconds(1));
46
p.setValue(std::make_shared<Data>(Data{123, "Data object"})); // 返回 std::shared_ptr<Data>
47
}).detach();
48
return promise.getFuture();
49
}
50
51
52
int main() {
53
auto sumFuture = asyncCalculateSum(); // Future<int>
54
auto nameFuture = asyncFetchUserName(123); // Future<std::string>
55
auto logFuture = asyncLogEvent(); // Future<void>
56
auto dataFuture = asyncCreateData(); // Future<std::shared_ptr<Data>>
57
58
// ... 使用 Future ...
59
60
return 0;
61
}
这些例子展示了 Future<T>
如何使用不同的模板参数 T
来表示不同类型的异步操作结果,体现了 Future
类型系统的灵活性和强大性。
2.5 Promise<T>
的模板参数:类型系统 (Template Parameter of Promise<T>
: Type System)
与 Future<T>
类似,folly::Promise<T>
也是一个模板类,其模板参数 T
也定义了 Promise
对象所承诺的 Future 结果的类型。Promise<T>
的模板参数 T
必须与与之关联的 Future<T>
的模板参数 类型一致。这种类型一致性是类型安全的基础,也是 Future
和 Promise
协同工作的关键。
模板参数 T
的约束 (Constraints of Template Parameter T
):
Promise<T>
的模板参数 T
必须与它所关联的 Future<T>
的模板参数 完全一致。这意味着,如果你创建了一个 Promise<int>
,那么你只能通过这个 Promise
设置一个 int
类型的值(或一个可以隐式转换为 int
类型的值)给与之关联的 Future<int>
。
类型一致性的重要性 (Importance of Type Consistency):
① 类型安全 (Type Safety): 类型一致性是保证类型安全的关键。它防止了在异步操作中出现类型不匹配的错误。编译器会在编译时检查 Promise
设置的值的类型是否与 Promise
的模板参数 T
匹配,从而在早期发现类型错误。
② 避免运行时错误 (Avoiding Runtime Errors): 类型不一致可能导致运行时错误,例如类型转换失败或意外的数据类型。通过强制类型一致性,folly/futures
库可以减少这类运行时错误的发生,提高程序的可靠性。
③ 代码可读性和可维护性 (Code Readability and Maintainability): 显式的类型参数使得代码更易于理解和维护。通过查看 Promise<T>
和 Future<T>
的声明,可以清晰地知道异步操作的结果类型,从而更好地理解异步流程。
示例 (Examples):
1
#include <folly/futures/Future.h>
2
#include <folly/futures/Promise.h>
3
#include <iostream>
4
#include <string>
5
#include <stdexcept>
6
7
using namespace folly;
8
9
int main() {
10
Promise<int> intPromise; // Promise<int> 承诺 Future<int> 的结果
11
Future<int> intFuture = intPromise.getFuture();
12
13
intPromise.setValue(123); // 正确:设置 int 类型的值
14
15
// intPromise.setValue("abc"); // 错误:类型不匹配,编译错误,不能将 std::string 设置给 Promise<int>
16
17
Promise<std::string> stringPromise; // Promise<std::string> 承诺 Future<std::string> 的结果
18
Future<std::string> stringFuture = stringPromise.getFuture();
19
20
stringPromise.setValue("Hello, Future!"); // 正确:设置 std::string 类型的值
21
22
// stringPromise.setValue(456); // 错误:类型不匹配,编译错误,不能将 int 设置给 Promise<std::string>
23
24
Promise<void> voidPromise; // Promise<void> 承诺 Future<void> 的结果
25
Future<void> voidFuture = voidPromise.getFuture();
26
27
voidPromise.setValue(); // 正确:设置 void 类型的值 (实际上不需要参数)
28
29
Promise<std::runtime_error> exceptionPromise; // Promise<std::runtime_error> 承诺 Future<std::runtime_error> 的结果 (用于设置异常)
30
Future<std::runtime_error> exceptionFuture = exceptionPromise.getFuture();
31
32
exceptionPromise.setException(std::runtime_error("Something went wrong")); // 正确:设置 std::runtime_error 类型的异常
33
34
35
return 0;
36
}
这些例子展示了 Promise<T>
的类型参数 T
的约束和类型一致性的重要性。编译器会强制执行类型检查,确保 Promise
只能设置与其模板参数类型匹配的值或异常,从而保证了类型安全。
END_OF_CHAPTER
3. chapter 3: Future 的基本操作 (Basic Operations of Future)
3.1 创建 Future 对象 (Creating Future Objects)
在 folly/futures
库中,Future
代表着一个异步操作的最终结果。要使用 Future
,首先需要创建 Future
对象。folly
提供了多种创建 Future
对象的方式,本节将详细介绍几种常用的方法。
3.1.1 使用 Promise
创建 Future (Creating Future using Promise
)
Promise
(承诺)是 Future
的创建者和控制者。每一个 Future
对象都和一个 Promise
对象关联。Promise
负责设置 Future
的最终结果(值或异常),而 Future
则负责提供访问这个结果的接口。这是创建 Future
最基本也是最核心的方式。
① 创建 Promise
对象: 首先,你需要创建一个 Promise<T>
对象,其中 T
是 Future
将要持有的值的类型。例如,如果异步操作最终会返回一个 int
类型的值,则应创建 Promise<int>
。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
5
int main() {
6
folly::Promise<int> promise;
7
// ... 后续操作设置 promise 的值或异常
8
return 0;
9
}
② 获取关联的 Future
对象: Promise
对象创建后,可以通过调用 promise.getFuture()
方法来获取与之关联的 Future<T>
对象。这个 Future
对象在 Promise
被设置结果之前,其结果是未知的(pending 状态)。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
5
int main() {
6
folly::Promise<int> promise;
7
folly::Future<int> future = promise.getFuture();
8
// 现在 future 对象与 promise 关联,等待 promise 设置结果
9
return 0;
10
}
③ 设置 Promise
的结果: 要使 Future
最终完成,需要通过 Promise
对象来设置结果。可以使用 promise.setValue(value)
来设置 Future
的值,或者使用 promise.setException(exception)
来设置 Future
的异常。一旦 Promise
被设置了结果,与之关联的 Future
就会变为 ready 状态,并且可以通过 Future
对象访问这个结果。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <stdexcept>
4
#include <iostream>
5
6
int main() {
7
folly::Promise<int> promise;
8
folly::Future<int> future = promise.getFuture();
9
10
// 模拟异步操作完成,设置 Promise 的值
11
promise.setValue(42);
12
13
// 或者模拟异步操作失败,设置 Promise 的异常
14
// promise.setException(std::runtime_error("Something went wrong"));
15
16
return 0;
17
}
代码示例: 下面是一个完整的例子,展示如何使用 Promise
创建 Future
并设置值。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
5
int main() {
6
folly::Promise<std::string> promise;
7
folly::Future<std::string> future = promise.getFuture();
8
9
// 模拟异步操作,例如从网络读取数据
10
std::string data = "Hello, Future!";
11
promise.setValue(data); // 设置 Promise 的值
12
13
// 异步获取 Future 的结果 (后续章节会详细介绍)
14
future.thenValue([](const std::string& result) {
15
std::cout << "Future result: " << result << std::endl;
16
});
17
18
return 0;
19
}
在这个例子中,我们创建了一个 Promise<std::string>
和与之关联的 Future<std::string>
. 然后,我们模拟异步操作完成,并通过 promise.setValue()
设置了 Future
的值。最后,我们使用 thenValue()
方法异步地处理 Future
的结果(关于 thenValue()
的详细用法将在后续章节介绍)。
3.1.2 使用 makeFuture()
函数 (Using makeFuture()
Function)
folly
提供了 folly::makeFuture()
函数,用于更便捷地创建已经完成的 Future
对象。makeFuture()
可以接受一个值或者一个异常,并返回一个已经设置为该值或异常的 Future
。
① 使用值创建已完成的 Future
: folly::makeFuture(value)
可以创建一个立即完成,并且结果为 value
的 Future
对象。
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> futureWithValue = folly::makeFuture(100); // 创建一个值为 100 的 Future
6
7
futureWithValue.thenValue([](int value) {
8
std::cout << "Future with value: " << value << std::endl;
9
});
10
11
return 0;
12
}
② 使用异常创建已完成(异常)的 Future
: folly::makeFuture(exception_ptr)
可以创建一个立即完成,并且结果为指定异常的 Future
对象。你需要使用 std::make_exception_ptr
来创建异常指针。
1
#include <folly/futures/Future.h>
2
#include <stdexcept>
3
#include <iostream>
4
5
int main() {
6
auto exceptionPtr = std::make_exception_ptr(std::runtime_error("Failed to create future"));
7
folly::Future<int> futureWithException = folly::makeFuture<int>(exceptionPtr); // 创建一个异常 Future
8
9
futureWithException.thenTry([](folly::Try<int> result) {
10
if (result.hasException()) {
11
try {
12
result.throwException(); // 重新抛出异常以便捕获
13
} catch (const std::exception& e) {
14
std::cerr << "Future with exception: " << e.what() << std::endl;
15
}
16
} else {
17
std::cout << "Future value: " << result.value() << std::endl; // 不会执行到这里
18
}
19
});
20
21
return 0;
22
}
代码示例: 展示 makeFuture()
的用法。
1
#include <folly/futures/Future.h>
2
#include <stdexcept>
3
#include <iostream>
4
5
folly::Future<int> createSuccessfulFuture() {
6
return folly::makeFuture(200); // 返回一个值为 200 的 Future
7
}
8
9
folly::Future<int> createFailedFuture() {
10
return folly::makeFuture<int>(std::make_exception_ptr(std::logic_error("Intentional failure"))); // 返回一个异常 Future
11
}
12
13
int main() {
14
createSuccessfulFuture().thenValue([](int value) {
15
std::cout << "Successful future value: " << value << std::endl;
16
});
17
18
createFailedFuture().thenTry([](folly::Try<int> result) {
19
if (result.hasException()) {
20
try {
21
result.throwException();
22
} catch (const std::exception& e) {
23
std::cerr << "Failed future exception: " << e.what() << std::endl;
24
}
25
}
26
});
27
28
return 0;
29
}
makeFuture()
函数在单元测试、创建已知结果的 Future
或者将同步操作快速转换为异步操作时非常有用。
3.1.3 使用 Future::value()
和 Future::exception()
(Using Future::value()
and Future::exception()
)
Future
类本身也提供了静态方法 Future::value(value)
和 Future::exception(exception_ptr)
,它们的功能与 makeFuture()
类似,用于创建已经完成的 Future
对象。
① Future::value(value)
: 静态方法 Future::value(value)
返回一个已经完成,并且结果为 value
的 Future
对象。
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<double> futureWithValue = folly::Future<double>::value(3.14); // 创建一个值为 3.14 的 Future
6
7
futureWithValue.thenValue([](double value) {
8
std::cout << "Future::value: " << value << std::endl;
9
});
10
11
return 0;
12
}
② Future::exception(exception_ptr)
: 静态方法 Future::exception(exception_ptr)
返回一个已经完成,并且结果为指定异常的 Future
对象。同样需要使用 std::make_exception_ptr
创建异常指针。
1
#include <folly/futures/Future.h>
2
#include <stdexcept>
3
#include <iostream>
4
5
int main() {
6
auto exceptionPtr = std::make_exception_ptr(std::out_of_range("Index out of bounds"));
7
folly::Future<int> futureWithException = folly::Future<int>::exception(exceptionPtr); // 创建一个异常 Future
8
9
futureWithException.thenTry([](folly::Try<int> result) {
10
if (result.hasException()) {
11
try {
12
result.throwException();
13
} catch (const std::exception& e) {
14
std::cerr << "Future::exception: " << e.what() << std::endl;
15
}
16
}
17
});
18
19
return 0;
20
}
代码示例: 展示 Future::value()
和 Future::exception()
的用法。
1
#include <folly/futures/Future.h>
2
#include <stdexcept>
3
#include <iostream>
4
5
folly::Future<std::string> createValueFuture() {
6
return folly::Future<std::string>::value("Success!");
7
}
8
9
folly::Future<std::string> createExceptionFuture() {
10
return folly::Future<std::string>::exception(std::make_exception_ptr(std::runtime_error("Operation failed")));
11
}
12
13
int main() {
14
createValueFuture().thenValue([](const std::string& value) {
15
std::cout << "Value Future result: " << value << std::endl;
16
});
17
18
createExceptionFuture().thenTry([](folly::Try<std::string> result) {
19
if (result.hasException()) {
20
try {
21
result.throwException();
22
} catch (const std::exception& e) {
23
std::cerr << "Exception Future error: " << e.what() << std::endl;
24
}
25
}
26
});
27
28
return 0;
29
}
Future::value()
和 Future::exception()
与 makeFuture()
在功能上非常相似,选择使用哪种方式通常取决于个人偏好和代码风格。它们都提供了一种便捷的方式来创建已经完成的 Future
对象,这在某些场景下非常有用。
3.2 获取 Future 的结果 (Getting the Result of a Future)
创建 Future
对象之后,下一步就是获取 Future
代表的异步操作的结果。folly::Future
提供了多种方法来获取结果,包括同步等待结果和异步处理结果。
3.2.1 get()
方法:同步等待结果 (get()
Method: Synchronous Waiting for Result)
Future::get()
方法是最直接获取 Future
结果的方式。它会阻塞当前线程,直到 Future
变为 ready 状态(即结果已设置),然后返回 Future
的值。如果 Future
最终以异常结束,get()
方法会抛出该异常。
① 基本用法: 调用 future.get()
会同步等待 Future
完成并返回值。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
#include <thread>
5
6
int main() {
7
folly::Promise<int> promise;
8
folly::Future<int> future = promise.getFuture();
9
10
std::thread t([&promise]() {
11
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟耗时操作
12
promise.setValue(50); // 1 秒后设置 Promise 的值
13
});
14
15
std::cout << "Waiting for future result..." << std::endl;
16
int result = future.get(); // 同步等待 Future 完成
17
std::cout << "Future result is: " << result << std::endl;
18
19
t.join();
20
return 0;
21
}
在这个例子中,future.get()
会阻塞 main
线程,直到另一个线程 t
设置了 promise
的值。一旦 promise.setValue(50)
被调用,future.get()
就会返回 50
,main
线程继续执行。
② 异常处理: 如果 Future
最终以异常结束,future.get()
会抛出该异常。因此,需要使用 try-catch
块来处理可能发生的异常。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <stdexcept>
4
#include <iostream>
5
#include <thread>
6
7
int main() {
8
folly::Promise<int> promise;
9
folly::Future<int> future = promise.getFuture();
10
11
std::thread t([&promise]() {
12
std::this_thread::sleep_for(std::chrono::seconds(1));
13
promise.setException(std::runtime_error("Async operation failed")); // 设置 Promise 的异常
14
});
15
16
std::cout << "Waiting for future result..." << std::endl;
17
try {
18
int result = future.get(); // 同步等待 Future 完成,可能抛出异常
19
std::cout << "Future result is: " << result << std::endl; // 不会执行到这里
20
} catch (const std::exception& e) {
21
std::cerr << "Caught exception: " << e.what() << std::endl;
22
}
23
24
t.join();
25
return 0;
26
}
在这个例子中,由于 promise.setException()
设置了异常,future.get()
会抛出 std::runtime_error
异常,并在 catch
块中被捕获和处理。
注意事项:
⚝ 阻塞线程: get()
方法会阻塞当前线程,因此在需要保持程序响应性的场景中应谨慎使用。在 GUI 线程或事件循环线程中调用 get()
可能会导致界面卡顿或程序无响应。
⚝ 异常传播: get()
方法会传播 Future
中存储的异常。如果异步操作失败,调用 get()
的线程会接收到这个异常。
⚝ 适用场景: get()
方法通常适用于以下场景:
▮▮▮▮⚝ 在程序的 main
函数或者程序的退出阶段,需要同步等待所有异步操作完成。
▮▮▮▮⚝ 在测试代码中,需要同步验证异步操作的结果。
▮▮▮▮⚝ 在某些命令行工具或脚本中,同步等待结果是可接受的。
在大多数异步编程场景中,更推荐使用异步方式处理 Future
的结果,例如使用 then()
方法,以避免阻塞线程。
3.2.2 then()
方法:异步处理结果 (then()
Method: Asynchronous Result Handling)
then()
方法是 folly::Future
中最核心的方法之一,用于异步地处理 Future
的结果。它允许你注册一个回调函数,当 Future
完成时(无论是成功返回结果还是抛出异常),这个回调函数会被异步执行。then()
方法返回一个新的 Future
,这使得可以链式地进行异步操作。
① 基本用法: then()
方法接受一个回调函数作为参数。这个回调函数会在 Future
完成后被调用。回调函数的参数是前一个 Future
的结果,返回值会成为新的 Future
的结果。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
5
int main() {
6
folly::Promise<int> promise;
7
folly::Future<int> future = promise.getFuture();
8
9
future.then([](folly::Try<int> result) { // 使用 then 处理 Future 的结果 (Try 对象)
10
if (result.hasValue()) {
11
std::cout << "Future result (from then): " << result.value() << std::endl;
12
} else if (result.hasException()) {
13
try {
14
result.throwException();
15
} catch (const std::exception& e) {
16
std::cerr << "Future exception (from then): " << e.what() << std::endl;
17
}
18
}
19
return folly::makeFuture(); // then 的回调需要返回一个 Future,这里返回 void Future
20
});
21
22
promise.setValue(60); // 设置 Promise 的值
23
24
// 注意:程序可能在回调执行前结束,实际应用中需要保证程序存活直到异步操作完成
25
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 简单等待回调执行完成
26
return 0;
27
}
在这个例子中,我们使用 future.then()
注册了一个回调函数。当 promise.setValue(60)
被调用,Future
完成后,then
注册的回调函数会被异步执行,打印出 Future
的结果。
② folly::Try<T>
参数: then()
方法的回调函数接收一个 folly::Try<T>
类型的参数。Try<T>
是 folly
库中用于表示可能成功或失败的结果的类。它可以包含一个类型为 T
的值(表示成功结果),或者一个异常(表示失败结果)。
⚝ result.hasValue()
: 判断 Try
对象是否包含值(即操作成功)。
⚝ result.value()
: 获取 Try
对象包含的值。只有当 hasValue()
返回 true
时才能安全调用。
⚝ result.hasException()
: 判断 Try
对象是否包含异常(即操作失败)。
⚝ result.throwException()
: 抛出 Try
对象包含的异常。只有当 hasException()
返回 true
时才能调用。
③ 链式调用: then()
方法返回一个新的 Future
。这允许你将多个异步操作链接在一起,形成一个异步操作链。每个 then()
方法的回调函数的返回值会决定下一个 Future
的结果。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
5
folly::Future<int> asyncOperation1() {
6
folly::Promise<int> promise;
7
std::thread t([&promise]() {
8
std::this_thread::sleep_for(std::chrono::milliseconds(500));
9
promise.setValue(10);
10
});
11
t.detach();
12
return promise.getFuture();
13
}
14
15
folly::Future<int> asyncOperation2(int value) {
16
folly::Promise<int> promise;
17
std::thread t([&promise, value]() {
18
std::this_thread::sleep_for(std::chrono::milliseconds(500));
19
promise.setValue(value * 2);
20
});
21
t.detach();
22
return promise.getFuture();
23
}
24
25
int main() {
26
asyncOperation1()
27
.then([](folly::Try<int> result1) {
28
if (result1.hasValue()) {
29
return asyncOperation2(result1.value()); // 链式调用 asyncOperation2
30
} else {
31
return folly::makeFuture<int>(result1.exceptionPtr()); // 传递异常
32
}
33
})
34
.then([](folly::Try<int> finalResult) {
35
if (finalResult.hasValue()) {
36
std::cout << "Final result: " << finalResult.value() << std::endl;
37
} else if (finalResult.hasException()) {
38
try {
39
finalResult.throwException();
40
} catch (const std::exception& e) {
41
std::cerr << "Error in chain: " << e.what() << std::endl;
42
}
43
}
44
return folly::makeFuture(); // 链式末端返回 void Future
45
});
46
47
std::this_thread::sleep_for(std::chrono::seconds(2)); // 等待异步操作完成
48
return 0;
49
}
在这个链式调用的例子中,asyncOperation1()
的结果作为 asyncOperation2()
的输入。通过 then()
方法,我们实现了异步操作的顺序执行。如果 asyncOperation1()
成功,则执行 asyncOperation2()
;如果 asyncOperation1()
失败,异常会被传递到链的末端。
then()
的变体: folly::Future
提供了多种 then()
的变体,以更方便地处理不同场景:
⚝ thenValue(callback)
: 只处理成功的结果(value)。如果前一个 Future
成功完成,则调用 callback
。
⚝ thenError(callback)
: 只处理异常的结果(exception)。如果前一个 Future
抛出异常,则调用 callback
。
⚝ thenTry(callback)
: 处理所有结果(value 和 exception)。与 then()
类似,但更明确地表明处理 Try
对象。
这些变体方法将在后续章节中详细介绍。then()
方法是构建复杂异步逻辑的基础,掌握 then()
的用法对于理解和使用 folly::Future
至关重要。
3.3 Future 的状态 (States of Future)
Future
对象在其生命周期中会经历不同的状态。了解 Future
的状态对于正确地管理和使用异步操作至关重要。folly::Future
提供了一些方法来查询 Future
的当前状态。
3.3.1 isReady()
:检查 Future 是否完成 (isReady()
: Checking if Future is Ready)
Future::isReady()
方法用于检查 Future
是否已经完成,即是否已经设置了结果(值或异常)。如果 Future
已经完成,isReady()
返回 true
,否则返回 false
。
① 基本用法: 调用 future.isReady()
检查 Future
是否完成。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
#include <thread>
5
6
int main() {
7
folly::Promise<int> promise;
8
folly::Future<int> future = promise.getFuture();
9
10
std::cout << "Is future ready initially? " << future.isReady() << std::endl; // 初始状态,未完成
11
12
std::thread t([&promise]() {
13
std::this_thread::sleep_for(std::chrono::milliseconds(500));
14
promise.setValue(70); // 500ms 后设置 Promise 的值
15
});
16
17
std::this_thread::sleep_for(std::chrono::milliseconds(200));
18
std::cout << "Is future ready after 200ms? " << future.isReady() << std::endl; // 仍然未完成
19
20
std::this_thread::sleep_for(std::chrono::milliseconds(500));
21
std::cout << "Is future ready after 700ms? " << future.isReady() << std::endl; // 已完成
22
23
t.join();
24
return 0;
25
}
在这个例子中,我们首先检查了 Future
的初始状态,此时 isReady()
返回 false
。在另一个线程设置 Promise
的值之后,再次检查 Future
的状态,此时 isReady()
返回 true
。
② 应用场景: isReady()
方法常用于以下场景:
⚝ 轮询检查: 在某些需要定期检查异步操作是否完成的场景中,可以使用 isReady()
进行轮询。但通常更推荐使用异步回调的方式,例如 then()
,而不是轮询。
⚝ 条件判断: 在某些复杂的逻辑中,可能需要根据 Future
是否完成来决定下一步的操作。
注意事项: isReady()
只是检查 Future
是否完成,并不能获取 Future
的结果。要获取结果,仍然需要使用 get()
或 then()
等方法。
3.3.2 isCancelled()
:检查 Future 是否被取消 (isCancelled()
: Checking if Future is Cancelled)
Future::isCancelled()
方法用于检查 Future
是否被取消。取消是一种提前终止异步操作的机制。如果 Future
被取消,isCancelled()
返回 true
,否则返回 false
。
① 基本用法: 调用 future.isCancelled()
检查 Future
是否被取消。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
#include <thread>
5
6
int main() {
7
folly::Promise<int> promise;
8
folly::Future<int> future = promise.getFuture();
9
10
std::cout << "Is future cancelled initially? " << future.isCancelled() << std::endl; // 初始状态,未取消
11
12
future.cancel(); // 取消 Future
13
14
std::cout << "Is future cancelled after cancel()? " << future.isCancelled() << std::endl; // 已取消
15
16
return 0;
17
}
在这个例子中,我们首先检查了 Future
的初始状态,isCancelled()
返回 false
。然后,我们调用 future.cancel()
取消了 Future
,再次检查 isCancelled()
,返回 true
。
② 取消传播: 取消操作可以传播到相关的 Future
链。如果一个 Future
被取消,通过 then()
等方法创建的后续 Future
也可能被取消。取消的传播和协作机制将在后续章节详细介绍。
③ 应用场景: isCancelled()
方法常用于以下场景:
⚝ 资源清理: 当 Future
被取消时,可能需要执行一些资源清理操作,例如释放已分配的内存、关闭网络连接等。可以使用 isCancelled()
来判断是否需要执行这些清理操作。
⚝ 避免不必要的工作: 在复杂的异步操作链中,如果某个环节的 Future
被取消,后续的异步操作可能不再需要执行。可以使用 isCancelled()
来提前终止后续操作,节省资源。
注意事项: isCancelled()
只是检查 Future
是否被取消,并不能阻止异步操作的实际执行。取消机制的有效性依赖于异步操作本身是否支持取消,以及是否正确地响应取消信号。
3.3.3 hasValue()
和 hasException()
:检查 Future 结果类型 (hasValue()
and hasException()
: Checking Future Result Type)
Future
完成时,可能成功返回一个值,也可能因为异常而失败。folly::Future
提供了 hasValue()
和 hasException()
方法来检查 Future
完成的结果类型。
① hasValue()
: Future::hasValue()
方法用于检查 Future
是否成功完成并持有一个值。如果 Future
成功完成,hasValue()
返回 true
,否则返回 false
(包括 Future
抛出异常或尚未完成)。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
5
int main() {
6
folly::Promise<int> promiseValue;
7
folly::Future<int> futureValue = promiseValue.getFuture();
8
9
promiseValue.setValue(80); // 设置 Promise 的值
10
11
std::cout << "Future with value - hasValue(): " << futureValue.hasValue() << std::endl; // true
12
std::cout << "Future with value - hasException(): " << futureValue.hasException() << std::endl; // false
13
14
folly::Promise<int> promiseException;
15
folly::Future<int> futureException = promiseException.getFuture();
16
17
promiseException.setException(std::runtime_error("Test exception")); // 设置 Promise 的异常
18
19
std::cout << "Future with exception - hasValue(): " << futureException.hasValue() << std::endl; // false
20
std::cout << "Future with exception - hasException(): " << futureException.hasException() << std::endl; // true
21
22
folly::Promise<int> promisePending;
23
folly::Future<int> futurePending = promisePending.getFuture();
24
25
std::cout << "Pending future - hasValue(): " << futurePending.hasValue() << std::endl; // false
26
std::cout << "Pending future - hasException(): " << futurePending.hasException() << std::endl; // false
27
28
return 0;
29
}
② hasException()
: Future::hasException()
方法用于检查 Future
是否因为异常而失败完成。如果 Future
抛出异常,hasException()
返回 true
,否则返回 false
(包括 Future
成功返回值或尚未完成)。
应用场景: hasValue()
和 hasException()
方法常用于以下场景:
⚝ 结果类型判断: 在需要根据 Future
的结果类型(成功或失败)执行不同操作时,可以使用这两个方法进行判断。例如,在 thenTry()
的回调函数中,可以使用 hasValue()
和 hasException()
来区分成功和失败的情况。
⚝ 错误处理: 在某些错误处理逻辑中,可能需要明确知道 Future
是因为异常而失败,以便采取相应的错误恢复或报告措施。
注意事项: hasValue()
和 hasException()
只能在 Future
完成后才能得到有意义的结果。对于尚未完成的 Future
,这两个方法都会返回 false
。
通过 isReady()
, isCancelled()
, hasValue()
, 和 hasException()
这些状态查询方法,可以全面了解 Future
的当前状态和结果类型,从而更好地控制和处理异步操作。
END_OF_CHAPTER
4. chapter 4: Promise 的基本操作 (Basic Operations of Promise)
4.1 创建 Promise 对象 (Creating Promise Objects)
在 folly/futures
库中,Promise<T>
是用于设置 Future<T>
结果的核心组件。要使用 Promise
,首先需要创建 Promise
对象。folly::Promise<T>
提供了多种构造方式,允许你根据不同的场景创建 Promise
实例。
最基本的创建 Promise
对象的方式是使用其默认构造函数。
1
#include <folly/futures/Promise.h>
2
#include <iostream>
3
4
int main() {
5
// 创建一个 Promise<int> 对象
6
folly::Promise<int> promise;
7
8
// 可以选择性地为 Promise 命名,方便调试和跟踪
9
folly::Promise<std::string> namedPromise{"MyPromise"};
10
11
std::cout << "Promise 对象已创建" << std::endl;
12
return 0;
13
}
上述代码展示了如何创建 Promise<int>
和 Promise<std::string>
类型的对象。Promise
对象被创建后,它处于未完成(unfulfilled)状态,等待被设置结果。你可以根据需要创建不同类型的 Promise
,例如 Promise<void>
用于表示没有返回值的异步操作。
除了默认构造函数,Promise
还可以接受一个可选的名称参数,这在调试复杂的异步流程时非常有用。通过命名 Promise
,你可以在日志或调试器中更容易地追踪异步操作的执行流程。
在实际应用中,Promise
对象通常在异步操作的发起端创建,并传递到执行异步操作的函数或模块中。异步操作完成后,通过 Promise
对象来设置 Future
的结果,从而完成整个异步流程。
4.2 设置 Promise 的结果 (Setting the Result of a Promise)
Promise
的主要作用是为与之关联的 Future
设置结果。结果可以是正常的值,也可以是异常。folly::Promise<T>
提供了 setValue(T value)
和 setException(exception_ptr ex)
两个核心方法来设置 Future
的结果。
4.2.1 setValue()
:设置 Future 的值 (setValue()
: Setting the Value of Future)
setValue(T value)
方法用于设置 Promise
关联的 Future
的正常结果值。当异步操作成功完成并产生一个值时,应该调用 setValue()
方法,并将结果值作为参数传递给它。一旦 setValue()
被调用,与该 Promise
关联的 Future
将变为完成(fulfilled)状态,并且可以通过 then()
等方法获取到设置的值。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
5
int main() {
6
folly::Promise<int> promise;
7
folly::Future<int> future = promise.getFuture();
8
9
// 模拟异步操作成功完成,结果值为 42
10
int result = 42;
11
promise.setValue(result);
12
13
// Future 已经完成,可以获取结果
14
future.thenValue([](int value) {
15
std::cout << "Future 成功完成,结果值为: " << value << std::endl;
16
});
17
18
return 0;
19
}
在上述代码中,我们首先创建了一个 Promise<int>
对象 promise
,并通过 promise.getFuture()
获取了与之关联的 Future<int>
对象 future
。然后,我们模拟异步操作成功完成,并将结果值 42
通过 promise.setValue(result)
设置给 Promise
。此时,future
变为完成状态,thenValue()
回调函数被执行,输出 "Future 成功完成,结果值为: 42"。
注意:setValue()
只能被调用一次。如果 Promise
已经设置过值或异常,再次调用 setValue()
将会抛出异常,表示 Promise
的状态已经被设置,不能重复设置。
4.2.2 setException()
:设置 Future 的异常 (setException()
: Setting the Exception of Future)
setException(exception_ptr ex)
方法用于设置 Promise
关联的 Future
的异常结果。当异步操作执行过程中发生错误或异常时,应该调用 setException()
方法,并将表示异常的 exception_ptr
对象作为参数传递给它。exception_ptr
是 C++ 标准库中用于传递异常的对象,可以使用 std::make_exception_ptr()
函数创建。一旦 setException()
被调用,与该 Promise
关联的 Future
将变为完成(rejected)状态,并且可以通过 thenError()
或 catch()
等方法捕获和处理异常。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <stdexcept>
4
#include <iostream>
5
6
int main() {
7
folly::Promise<int> promise;
8
folly::Future<int> future = promise.getFuture();
9
10
// 模拟异步操作发生异常
11
std::exception_ptr exception = std::make_exception_ptr(std::runtime_error("异步操作失败"));
12
promise.setException(exception);
13
14
// Future 已经完成,但结果是异常
15
future.thenValue([](int value) {
16
// 不会被执行,因为 Future 结果是异常
17
std::cout << "Future 成功完成,结果值为: " << value << std::endl;
18
}).thenError([](const std::runtime_error& error) {
19
std::cout << "Future 异常完成,异常信息: " << error.what() << std::endl;
20
});
21
22
return 0;
23
}
在上述代码中,我们模拟异步操作发生了一个 std::runtime_error
异常,并使用 std::make_exception_ptr()
创建了 exception_ptr
对象 exception
。然后,通过 promise.setException(exception)
将异常设置给 Promise
。此时,future
变为完成状态,但结果是异常。thenValue()
回调函数不会被执行,而 thenError()
回调函数会被执行,捕获并处理异常,输出 "Future 异常完成,异常信息: 异步操作失败"。
注意:与 setValue()
类似,setException()
也只能被调用一次。如果 Promise
已经设置过值或异常,再次调用 setException()
同样会抛出异常。
4.3 获取 Promise 关联的 Future (Getting the Future Associated with Promise)
Promise
对象本身并不直接持有异步操作的结果,它只是一个设置结果的入口。真正代表异步操作结果的是与 Promise
关联的 Future
对象。要获取与 Promise
对象关联的 Future
,需要调用 Promise::getFuture()
方法。
getFuture()
方法返回一个 folly::Future<T>
对象,该 Future
对象与调用 getFuture()
方法的 Promise
对象关联。这意味着,当 Promise
对象通过 setValue()
或 setException()
设置结果后,这个 Future
对象的状态也会相应地变为完成状态,并且可以通过 Future
的各种操作(如 then()
, get()
, wait()
等)来获取结果或处理完成后的操作。
1
#include <folly/futures/Promise.h>
2
#include <folly/futures/Future.h>
3
#include <iostream>
4
#include <thread>
5
#include <chrono>
6
7
int main() {
8
folly::Promise<int> promise;
9
folly::Future<int> future = promise.getFuture();
10
11
// 模拟在另一个线程中执行异步操作
12
std::thread workerThread([&promise]() {
13
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作
14
promise.setValue(100); // 异步操作完成,设置 Promise 的值
15
});
16
17
// 在主线程中等待 Future 完成并获取结果
18
future.thenValue([](int value) {
19
std::cout << "异步操作结果: " << value << std::endl;
20
});
21
22
workerThread.join(); // 等待工作线程结束
23
return 0;
24
}
在上述代码示例中,我们在主线程中创建了一个 Promise<int>
对象 promise
,并调用 promise.getFuture()
获取了关联的 Future<int>
对象 future
。然后,我们创建了一个新的线程 workerThread
来模拟执行异步操作。在 workerThread
中,我们休眠 2 秒钟来模拟耗时操作,然后调用 promise.setValue(100)
设置 Promise
的值。在主线程中,我们通过 future.thenValue()
注册了一个回调函数,当 future
完成时,该回调函数会被执行,输出异步操作的结果。
关键点:
① 关联性:Promise
和 Future
通过 getFuture()
方法建立关联,一个 Promise
对象只能被 getFuture()
调用一次,多次调用会抛出异常。
② 单向性:Promise
用于设置 Future
的结果,而 Future
用于获取结果和注册后续操作。它们是异步编程中生产者和消费者的角色。
③ 及时性:getFuture()
方法应该在 Promise
对象创建后尽快调用,以便尽早获得 Future
对象并开始注册后续操作。
4.4 Promise 的生命周期管理 (Lifecycle Management of Promise)
Promise
的生命周期管理是理解和正确使用 folly::Promise
的重要方面。Promise
的生命周期主要包括创建、设置结果和销毁三个阶段。
① 创建阶段:Promise
对象被创建时,它处于未完成(unfulfilled)状态。此时,与之关联的 Future
对象也处于未完成状态。Promise
对象可以被命名,方便调试和跟踪。
② 设置结果阶段:在异步操作完成后,通过调用 Promise::setValue()
或 Promise::setException()
方法来设置 Promise
的结果。一旦结果被设置,Promise
的状态变为已完成(fulfilled 或 rejected),并且不能再次设置结果。任何尝试重复设置结果的操作都会导致异常。与 Promise
关联的 Future
对象的状态也会同步更新为完成状态,并触发已注册的回调函数。
③ 销毁阶段:当 Promise
对象超出作用域或被显式销毁时,Promise
对象本身占用的资源会被释放。但是,需要特别注意的是,Promise
对象的销毁并不会影响与之关联的 Future
对象的生命周期。即使 Promise
对象被销毁,Future
对象仍然可以继续存在,并且可以被等待或查询状态,直到异步操作真正完成。
生命周期管理的关键考虑:
⚝ 避免过早销毁 Promise
: 确保在异步操作完成之前,Promise
对象保持有效。如果 Promise
对象在异步操作完成之前被销毁,可能会导致程序行为异常,甚至崩溃。通常,Promise
对象应该在其关联的异步操作的生命周期内保持有效。
⚝ Future
的独立生命周期: Future
对象的生命周期与 Promise
对象是独立的。Future
对象可以安全地传递到不同的模块或线程,即使原始的 Promise
对象已经被销毁。Future
对象会一直存在,直到异步操作完成,并且结果被处理。
⚝ 资源管理: Promise
对象本身通常不持有大量的资源。但是,如果异步操作涉及到资源管理(例如,文件句柄、网络连接等),则需要在异步操作完成时,在设置 Promise
结果之前或之后,正确地释放这些资源。可以使用 RAII (Resource Acquisition Is Initialization) 技术来管理异步操作中的资源,确保资源在不再需要时被及时释放。
⚝ 异常安全: 在异步操作中,要充分考虑异常安全。即使异步操作抛出异常,也应该确保 Promise
对象能够被正确地设置异常结果,并且资源能够被正确地释放。可以使用 try-catch 块来捕获异步操作中的异常,并在 catch 块中调用 Promise::setException()
来设置异常结果。
理解 Promise
的生命周期管理对于编写健壮和可靠的异步程序至关重要。正确地管理 Promise
的生命周期,可以避免资源泄漏、程序崩溃等问题,并确保异步操作的正确执行和结果处理。
END_OF_CHAPTER
5. chapter 5: Future 的链式操作 (Chaining Operations of Future)
5.1 then()
:顺序执行异步操作 (then()
: Sequential Execution of Asynchronous Operations)
Future
最强大的特性之一就是链式操作(chaining operations),它允许我们以同步代码的风格来组织和管理异步操作序列。then()
方法是实现链式操作的核心,它允许我们在一个 Future
对象完成(无论是成功返回结果还是抛出异常)后,继续执行下一步操作。这种方式避免了传统回调地狱(callback hell)的问题,使得异步代码更加清晰和易于维护。
then()
方法返回一个新的 Future
对象,这个新的 Future
对象代表了链式操作的下一步结果。then()
接受一个回调函数作为参数,这个回调函数会在原始 Future
完成后被异步调用。回调函数的返回值会被包装成一个新的 Future
对象,作为 then()
方法的返回值。
5.1.1 thenValue()
:处理 Future 的值 (thenValue()
: Handling the Value of Future)
thenValue()
是 then()
的一个变体,专门用于处理 Future
成功完成并返回结果值的情况。它接受一个函数作为参数,该函数只会在前一个 Future
成功完成时被调用,并将前一个 Future
的结果值作为参数传递给该函数。
示例代码:
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
5
using namespace folly;
6
7
Future<int> fetchData() {
8
return makeFuture(42);
9
}
10
11
int processData(int data) {
12
std::cout << "Processing data: " << data << std::endl;
13
return data * 2;
14
}
15
16
int main() {
17
fetchData()
18
.thenValue(processData)
19
.thenValue([](int result) {
20
std::cout << "Final result: " << result << std::endl;
21
})
22
.get(); // 同步等待整个 Future 链完成
23
24
return 0;
25
}
代码解释:
① fetchData()
函数返回一个 Future<int>
,模拟异步获取数据的操作,这里直接返回一个值为 42
的 Future
。
② processData()
函数接受一个 int
参数,模拟数据处理操作,将输入数据乘以 2 并返回。
③ fetchData().thenValue(processData)
创建了一个新的 Future
链。当 fetchData()
返回的 Future
成功完成时,processData()
函数会被调用,并将 fetchData()
的结果 42
作为参数传入。processData()
的返回值 84
会被包装成一个新的 Future<int>
。
④ .thenValue([](int result) { ... })
进一步链式调用 thenValue()
,处理 processData()
返回的 Future
的结果。lambda 函数接收 processData()
的结果 84
,并打印最终结果。
⑤ .get()
方法用于同步等待整个 Future
链完成,并获取最终结果(在这个例子中我们并不关心最终结果的值,只是为了等待链式操作完成)。
运行结果:
1
Processing data: 42
2
Final result: 84
要点总结:
⚝ thenValue()
专注于处理 Future
成功完成的情况。
⚝ 它接受一个函数,该函数以前一个 Future
的值为输入,并返回一个新的值(或 Future
)。
⚝ thenValue()
返回的 Future
代表了对前一个 Future
值的处理结果。
5.1.2 thenError()
:处理 Future 的异常 (thenError()
: Handling the Exception of Future)
与 thenValue()
相对,thenError()
用于处理 Future
异常完成的情况。它接受一个函数作为参数,该函数只会在前一个 Future
抛出异常时被调用,并将捕获到的异常作为参数传递给该函数。
示例代码:
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <stdexcept>
4
#include <iostream>
5
6
using namespace folly;
7
8
Future<int> fetchDataWithError(bool shouldFail) {
9
if (shouldFail) {
10
return makeFuture<int>(std::runtime_error("Failed to fetch data"));
11
} else {
12
return makeFuture(42);
13
}
14
}
15
16
int processDataOnError(const std::runtime_error& error) {
17
std::cerr << "Error processing data: " << error.what() << std::endl;
18
return -1; // 返回一个默认值或错误码
19
}
20
21
int main() {
22
fetchDataWithError(true) // 模拟获取数据失败
23
.thenValue([](int data) {
24
std::cout << "Data received: " << data << std::endl; // 不会被执行
25
return data * 2;
26
})
27
.thenError(processDataOnError)
28
.thenValue([](int result) {
29
std::cout << "Final result after error handling: " << result << std::endl;
30
})
31
.get();
32
33
fetchDataWithError(false) // 模拟获取数据成功
34
.thenValue([](int data) {
35
std::cout << "Data received: " << data << std::endl;
36
return data * 2;
37
})
38
.thenError(processDataOnError) // 不会被执行
39
.thenValue([](int result) {
40
std::cout << "Final result after successful path: " << result << std::endl;
41
})
42
.get();
43
44
return 0;
45
}
代码解释:
① fetchDataWithError(bool shouldFail)
函数根据 shouldFail
参数决定返回成功的 Future
还是抛出异常的 Future
。
② processDataOnError(const std::runtime_error& error)
函数接受一个 std::runtime_error
类型的异常对象,打印错误信息并返回一个默认值 -1
。
③ 第一个 Future
链模拟获取数据失败的情况。fetchDataWithError(true)
返回一个异常 Future
,thenValue()
的回调函数不会被执行,而是直接跳转到 thenError(processDataOnError)
。processDataOnError()
处理异常并返回 -1
。
④ 第二个 Future
链模拟获取数据成功的情况。fetchDataWithError(false)
返回一个成功的 Future
,thenValue()
的回调函数会被执行,thenError()
的回调函数不会被执行。
运行结果:
1
Error processing data: Failed to fetch data
2
Final result after error handling: -1
3
Data received: 42
4
Final result after successful path: 84
要点总结:
⚝ thenError()
专注于处理 Future
异常完成的情况。
⚝ 它接受一个函数,该函数以前一个 Future
的异常为输入,并返回一个新的值(或 Future
)。
⚝ thenError()
返回的 Future
代表了对前一个 Future
异常的处理结果,允许从错误中恢复或进行错误处理。
5.1.3 thenTry()
:处理 Future 的结果,包括值和异常 (thenTry()
: Handling Both Value and Exception of Future)
thenTry()
是 then()
的另一个变体,它提供了一种统一的方式来处理 Future
的完成,无论它是成功返回结果值还是抛出异常。thenTry()
接受一个函数作为参数,该函数会在前一个 Future
完成时被调用,并将一个 Try<T>
对象作为参数传递给该函数。Try<T>
是 folly
库中用于表示可能成功或失败的操作结果的类,它可以包含一个值(成功)或一个异常(失败)。
示例代码:
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <folly/Try.h>
4
#include <stdexcept>
5
#include <iostream>
6
7
using namespace folly;
8
9
Future<int> fetchDataWithTry(bool shouldFail) {
10
if (shouldFail) {
11
return makeFuture<int>(std::runtime_error("Fetch data failed in Try"));
12
} else {
13
return makeFuture(42);
14
}
15
}
16
17
int processDataWithTry(Try<int> resultTry) {
18
if (resultTry.isSuccess()) {
19
int data = resultTry.value();
20
std::cout << "Data received in Try: " << data << std::endl;
21
return data * 2;
22
} else {
23
std::cerr << "Error in Try: " << resultTry.exception().what() << std::endl;
24
return -1; // 返回错误码
25
}
26
}
27
28
int main() {
29
fetchDataWithTry(true)
30
.thenTry(processDataWithTry)
31
.thenValue([](int result) {
32
std::cout << "Final result from Try (error case): " << result << std::endl;
33
})
34
.get();
35
36
fetchDataWithTry(false)
37
.thenTry(processDataWithTry)
38
.thenValue([](int result) {
39
std::cout << "Final result from Try (success case): " << result << std::endl;
40
})
41
.get();
42
43
return 0;
44
}
代码解释:
① fetchDataWithTry(bool shouldFail)
函数与之前的 fetchDataWithError
类似,根据参数决定返回成功或失败的 Future
。
② processDataWithTry(Try<int> resultTry)
函数接受一个 Try<int>
对象。它使用 resultTry.isSuccess()
检查操作是否成功,如果是,则通过 resultTry.value()
获取值;否则,通过 resultTry.exception().what()
获取异常信息。
③ 无论 fetchDataWithTry()
返回成功还是失败的 Future
,thenTry(processDataWithTry)
都会被调用,并传递一个 Try<int>
对象,封装了 fetchDataWithTry()
的结果。
运行结果:
1
Error in Try: Fetch data failed in Try
2
Final result from Try (error case): -1
3
Data received in Try: 42
4
Final result from Try (success case): 84
要点总结:
⚝ thenTry()
提供了一种统一的方式来处理 Future
的成功和失败情况。
⚝ 它接受一个函数,该函数以前一个 Future
的 Try<T>
对象为输入。
⚝ 使用 Try<T>
可以方便地检查操作是否成功,并获取值或异常。
⚝ thenTry()
返回的 Future
代表了对前一个 Future
结果(成功或失败)的处理结果。
5.2 map()
:转换 Future 的值 (map()
: Transforming the Value of Future)
map()
方法用于转换 Future
对象的值,它类似于函数式编程中的 map
操作。map()
接受一个函数作为参数,该函数以前一个 Future
的成功结果值为输入,并返回一个新的值。map()
方法返回一个新的 Future
对象,这个新的 Future
对象会在前一个 Future
成功完成后,将前一个 Future
的值传递给 map()
的回调函数进行转换,并将转换后的值作为新 Future
的结果。
示例代码:
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
#include <string>
5
6
using namespace folly;
7
8
Future<int> fetchUserID() {
9
return makeFuture(123);
10
}
11
12
Future<std::string> fetchUserName(int userID) {
13
return makeFuture(std::string("User") + std::to_string(userID));
14
}
15
16
int main() {
17
fetchUserID()
18
.map(fetchUserName) // 将 int 类型的 Future 转换为 string 类型的 Future
19
.thenValue([](const std::string& userName) {
20
std::cout << "User name: " << userName << std::endl;
21
})
22
.get();
23
24
return 0;
25
}
代码解释:
① fetchUserID()
返回一个 Future<int>
,模拟异步获取用户 ID。
② fetchUserName(int userID)
返回一个 Future<std::string>
,根据用户 ID 异步获取用户名。
③ fetchUserID().map(fetchUserName)
使用 map()
方法将 Future<int>
转换为 Future<std::string>
。map()
的回调函数 fetchUserName
以前一个 Future<int>
的结果值(用户 ID)作为输入,并返回一个新的 Future<std::string>
(包含用户名的 Future
)。
④ .thenValue([](const std::string& userName) { ... })
处理 map()
返回的 Future<std::string>
的结果,打印用户名。
运行结果:
1
User name: User123
要点总结:
⚝ map()
用于转换 Future
的值类型。
⚝ 它接受一个函数,该函数以前一个 Future
的值作为输入,并返回一个新的值(或 Future
,如示例所示)。
⚝ map()
返回的 Future
的值类型可能与原始 Future
的值类型不同。
⚝ map()
只能处理成功的情况,如果原始 Future
抛出异常,异常会直接传递到 map()
返回的 Future
。
5.3 flatMap()
:扁平化 Future 的 Future (flatMap()
: Flattening Future of Future)
flatMap()
方法与 map()
方法类似,也用于转换 Future
的值,但它专门用于处理回调函数返回 Future
的情况,并进行“扁平化”处理。当 map()
的回调函数返回一个 Future
时,map()
会返回一个“嵌套”的 Future
,即 Future<Future<T>>
。而 flatMap()
则会将这种嵌套的 Future
扁平化为 Future<T>
,使得链式操作更加简洁。
示例代码:
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
5
using namespace folly;
6
7
Future<int> fetchOrderIDs() {
8
return makeFuture(1001);
9
}
10
11
Future<Future<std::string>> fetchOrderDetailsWithMap(int orderID) {
12
// 使用 map 返回 Future<Future<std::string>>
13
return makeFuture(orderID).map([](int id) {
14
return fetchOrderDetails(id); // fetchOrderDetails 返回 Future<std::string>
15
});
16
}
17
18
Future<std::string> fetchOrderDetailsWithFlatMap(int orderID) {
19
// 使用 flatMap 返回 Future<std::string>
20
return makeFuture(orderID).flatMap([](int id) {
21
return fetchOrderDetails(id); // fetchOrderDetails 返回 Future<std::string>
22
});
23
}
24
25
Future<std::string> fetchOrderDetails(int orderID) {
26
return makeFuture(std::string("Details for order ") + std::to_string(orderID));
27
}
28
29
30
int main() {
31
// 使用 map 的情况,需要额外的 thenValue 来解嵌套 Future
32
fetchOrderIDs()
33
.map(fetchOrderDetailsWithMap)
34
.thenValue([](Future<std::string> orderDetailsFuture) {
35
orderDetailsFuture.thenValue([](const std::string& orderDetails) {
36
std::cout << "Order details (using map): " << orderDetails << std::endl;
37
});
38
})
39
.get();
40
41
// 使用 flatMap 的情况,链式操作更简洁
42
fetchOrderIDs()
43
.flatMap(fetchOrderDetailsWithFlatMap)
44
.thenValue([](const std::string& orderDetails) {
45
std::cout << "Order details (using flatMap): " << orderDetails << std::endl;
46
})
47
.get();
48
49
return 0;
50
}
代码解释:
① fetchOrderIDs()
返回一个 Future<int>
,模拟异步获取订单 ID。
② fetchOrderDetails(int orderID)
返回一个 Future<std::string>
,根据订单 ID 异步获取订单详情。
③ fetchOrderDetailsWithMap(int orderID)
使用 map()
方法,其回调函数返回 fetchOrderDetails(id)
,这是一个 Future<std::string>
。因此 fetchOrderDetailsWithMap
返回的是 Future<Future<std::string>>
。
④ fetchOrderDetailsWithFlatMap(int orderID)
使用 flatMap()
方法,其回调函数同样返回 fetchOrderDetails(id)
,但 flatMap()
会将返回的 Future<Future<std::string>>
扁平化为 Future<std::string>
。
⑤ 在 main()
函数中,展示了使用 map()
和 flatMap()
的区别。使用 map()
时,需要额外的 .thenValue()
来处理嵌套的 Future
;而使用 flatMap()
时,链式操作更加简洁,可以直接处理 Future<std::string>
的结果。
运行结果:
1
Order details (using map): Details for order 1001
2
Order details (using flatMap): Details for order 1001
要点总结:
⚝ flatMap()
用于处理回调函数返回 Future
的情况,并进行扁平化。
⚝ 当回调函数返回 Future<T>
时,flatMap()
返回 Future<T>
,而不是 Future<Future<T>>
。
⚝ flatMap()
使得链式异步操作更加简洁,避免了嵌套 Future
的问题。
⚝ flatMap()
在需要顺序执行多个异步操作,并且后一个操作依赖前一个操作的异步结果时非常有用。
5.4 链式操作的错误处理 (Error Handling in Chaining Operations)
在 Future
的链式操作中,错误处理至关重要。如果链中的任何一个 Future
抛出异常,异常会沿着链传播下去,直到被显式地处理。folly::Future
提供了多种机制来处理链式操作中的错误:
① 异常传播 (Exception Propagation):默认情况下,如果链中的某个 Future
抛出异常,后续的 thenValue()
和 map()
等操作会被跳过,异常会直接传递到链的末端。
② thenError()
错误处理:可以使用 thenError()
方法在链中捕获和处理特定类型的异常。thenError()
允许从错误中恢复,或者进行一些清理操作。
③ thenTry()
统一处理:可以使用 thenTry()
方法统一处理成功和失败的情况,通过 Try<T>
对象来检查结果并处理异常。
④ catch()
和 catchError()
异常捕获:catch()
和 catchError()
方法提供了更细粒度的异常捕获机制,可以捕获特定类型的异常,并返回一个新的 Future
,从而从异常中恢复。
⑤ recover()
和 recoverWith()
异常恢复:recover()
和 recoverWith()
方法也用于从异常中恢复,它们与 catch()
和 catchError()
类似,但提供了更灵活的恢复策略。
最佳实践:
⚝ 尽早处理异常:在 Future
链中,应该尽早考虑错误处理,避免异常传播到链的末端才被处理,这样可以更清晰地定位错误发生的位置。
⚝ 使用 thenError()
或 thenTry()
进行局部错误处理:对于可能发生错误的操作,可以使用 thenError()
或 thenTry()
在链中进行局部错误处理,例如记录错误日志、返回默认值或进行重试。
⚝ 使用 catch()
或 recover()
进行全局错误处理:在链的末端,可以使用 catch()
或 recover()
进行全局错误处理,例如将错误转换为用户友好的提示信息、或者进行全局的错误监控和报警。
⚝ 避免忽略异常:在链式操作中,应该避免忽略异常,确保所有可能的错误情况都被考虑到并得到妥善处理。忽略异常可能会导致程序行为不可预测,甚至崩溃。
示例代码(错误处理):
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <stdexcept>
4
#include <iostream>
5
6
using namespace folly;
7
8
Future<int> mayFailOperation(int input) {
9
if (input < 0) {
10
return makeFuture<int>(std::runtime_error("Input cannot be negative"));
11
}
12
return makeFuture(input * 2);
13
}
14
15
int main() {
16
mayFailOperation(10)
17
.thenValue([](int result) {
18
std::cout << "Operation result: " << result << std::endl;
19
return result + 5;
20
})
21
.thenError([](const std::runtime_error& error) {
22
std::cerr << "Error occurred: " << error.what() << std::endl;
23
return -1; // 错误处理后返回一个默认值
24
})
25
.thenValue([](int finalResult) {
26
std::cout << "Final result after error handling (or success): " << finalResult << std::endl;
27
})
28
.get();
29
30
mayFailOperation(-5) // 触发异常
31
.thenValue([](int result) {
32
std::cout << "Operation result: " << result << std::endl; // 不会被执行
33
return result + 5;
34
})
35
.thenError([](const std::runtime_error& error) {
36
std::cerr << "Error occurred: " << error.what() << std::endl;
37
return -1; // 错误处理后返回一个默认值
38
})
39
.thenValue([](int finalResult) {
40
std::cout << "Final result after error handling (or success): " << finalResult << std::endl;
41
})
42
.get();
43
44
return 0;
45
}
运行结果:
1
Operation result: 20
2
Final result after error handling (or success): 25
3
Error occurred: Input cannot be negative
4
Final result after error handling (or success): -1
代码解释:
① mayFailOperation(int input)
函数模拟一个可能失败的操作,当输入小于 0 时抛出异常。
② 在 Future
链中,使用 thenError()
捕获 std::runtime_error
类型的异常,并打印错误信息,返回默认值 -1
。
③ 无论操作成功还是失败,最终都会执行最后一个 thenValue()
,打印最终结果。
通过合理地使用 Future
的链式操作和错误处理机制,可以构建清晰、健壮的异步程序。链式操作使得异步代码更易于理解和维护,而丰富的错误处理方法则保证了程序的可靠性。
END_OF_CHAPTER
6. chapter 6: Future 的组合操作 (Combination Operations of Future)
本章深入探讨 folly::Future
提供的强大组合操作,这些操作允许开发者有效地管理和协调多个异步任务。通过组合操作,可以构建更复杂、更灵活的异步流程,从而充分发挥异步编程的优势。我们将详细介绍 collect()
、select()
、race()
和 andThen()
等关键的组合方法,并通过实际的代码示例,展示如何在各种场景下应用这些技术。
6.1 collect()
:等待多个 Future 完成 (collect()
: Waiting for Multiple Futures to Complete)
collect()
是一个非常有用的 Future 组合操作,它允许你等待一组 Future
对象全部完成。当你有多个独立的异步任务需要并行执行,并且需要等待所有任务完成后才能进行下一步操作时,collect()
就派上了用场。
collect()
函数接受一个 Future
的容器(例如 std::vector<Future<T>>
),并返回一个新的 Future<std::vector<T>>
。这个新的 Future
将在输入容器中的所有 Future
都完成后完成。如果所有输入的 Future
都成功完成,那么返回的 Future
将会成功完成,并且其结果是一个包含所有输入 Future
结果的 std::vector
,结果的顺序与输入 Future
在容器中的顺序一致。如果任何一个输入的 Future
失败,那么返回的 Future
将会立即失败,并且携带第一个失败的 Future
的异常。
使用场景
collect()
适用于以下场景:
① 并行执行多个独立任务:例如,你需要同时从多个数据源获取数据,并将所有数据汇总后进行处理。
② 事务性操作:在分布式系统中,一个事务可能涉及多个子操作,你需要确保所有子操作都成功完成,事务才能提交。collect()
可以用来等待所有子操作的 Future 完成。
③ 批量处理:当你需要批量处理一组任务,并且希望等待所有任务都完成后再进行后续处理时。
代码示例
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
#include <vector>
5
6
using namespace folly;
7
8
Future<int> asyncTask(int value, int delayMs) {
9
return DelayedExecutor::schedule(std::chrono::milliseconds(delayMs), InlineExecutor::instance())
10
.thenValue([value](Unit) {
11
std::cout << "Task with value " << value << " completed." << std::endl;
12
return value;
13
});
14
}
15
16
int main() {
17
std::vector<Future<int>> futures;
18
futures.push_back(asyncTask(10, 100));
19
futures.push_back(asyncTask(20, 200));
20
futures.push_back(asyncTask(30, 50));
21
22
auto collectedFuture = collect(futures);
23
24
collectedFuture.thenValue([](std::vector<int> results) {
25
std::cout << "All tasks completed. Results: ";
26
for (int result : results) {
27
std::cout << result << " ";
28
}
29
std::cout << std::endl;
30
}).thenError([](const std::exception& e) {
31
std::cerr << "Error occurred: " << e.what() << std::endl;
32
});
33
34
// Normally you would need to block to wait for the future to complete in a main function
35
// For demonstration purposes, we are using InlineExecutor which executes synchronously in this example.
36
return 0;
37
}
代码解释
① asyncTask
函数模拟一个异步任务,它会在指定的延迟后完成,并返回一个 Future<int>
。
② 在 main
函数中,我们创建了一个 Future<int>
的 std::vector
,并向其中添加了三个异步任务。
③ 使用 collect(futures)
将这组 Future
组合成一个新的 Future
,collectedFuture
。
④ collectedFuture
的 thenValue
回调函数会在所有异步任务都成功完成后被调用,并打印所有任务的结果。
⑤ thenError
回调函数会在任何一个异步任务失败时被调用,并打印错误信息。
错误处理
如果任何一个输入的 Future
失败,collect()
返回的 Future
也会失败。这意味着,如果你的并行任务中,任何一个任务失败是不可接受的,那么 collect()
可以帮助你快速检测到错误并进行处理。你可以通过 thenError()
或 catch()
等方法来处理 collect()
返回的 Future
可能出现的异常。
6.2 select()
:选择最先完成的 Future (select()
: Selecting the First Completed Future)
与 collect()
等待所有 Future 完成不同,select()
操作关注的是一组 Future
中最先完成的那个。select()
函数接受一个 Future
的容器,并返回一个新的 Future<Try<T>>
。这个新的 Future
会在输入容器中第一个完成的 Future
完成时立即完成。
返回的 Future
的结果类型是 Try<T>
,这是一个 folly
库提供的工具类,用于表示可能成功也可能失败的结果。如果最先完成的 Future
成功完成,那么 Try<T>
将包含成功的值;如果最先完成的 Future
失败,那么 Try<T>
将包含异常。
使用场景
select()
适用于以下场景:
① 竞速请求:例如,你需要从多个镜像站点下载同一个资源,为了提高速度和可靠性,你可以向所有镜像站点同时发起请求,并使用 select()
选择最先返回结果的那个。
② 超时机制:你可以将一个实际的任务 Future 和一个超时 Future 放入 select()
中,如果超时 Future 先完成(通常是失败),则表示任务超时。
③ 备用方案:当一个主要服务不可用时,你可以尝试使用备用服务。你可以同时向主服务和备用服务发起请求,并使用 select()
选择最先响应的服务。
代码示例
1
#include <folly/Future.h>
2
#include <folly/Try.h>
3
#include <folly/executors/InlineExecutor.h>
4
#include <iostream>
5
#include <vector>
6
7
using namespace folly;
8
9
Future<std::string> fastTask(std::string name, int delayMs, bool shouldFail) {
10
return DelayedExecutor::schedule(std::chrono::milliseconds(delayMs), InlineExecutor::instance())
11
.thenValue([name, shouldFail](Unit) {
12
if (shouldFail) {
13
throw std::runtime_error(name + " task failed");
14
}
15
std::cout << name << " task completed first." << std::endl;
16
return name + " result";
17
});
18
}
19
20
int main() {
21
std::vector<Future<std::string>> futures;
22
futures.push_back(fastTask("Task A", 100, false));
23
futures.push_back(fastTask("Task B", 200, true));
24
futures.push_back(fastTask("Task C", 150, false));
25
26
auto selectedFuture = select(futures);
27
28
selectedFuture.thenValue([](Try<std::string> resultTry) {
29
if (resultTry.isSuccess()) {
30
std::cout << "First completed task result: " << resultTry.value() << std::endl;
31
} else {
32
std::cerr << "First completed task failed: " << resultTry.exception().what() << std::endl;
33
}
34
});
35
36
// Normally you would need to block to wait for the future to complete in a main function
37
// For demonstration purposes, we are using InlineExecutor which executes synchronously in this example.
38
return 0;
39
}
代码解释
① fastTask
函数模拟一个异步任务,它可以设置延迟时间和是否抛出异常。
② 在 main
函数中,我们创建了三个异步任务,Task A 最快完成,Task B 会失败,Task C 速度中等。
③ 使用 select(futures)
选择最先完成的任务。
④ selectedFuture
的 thenValue
回调函数接收一个 Try<std::string>
对象,我们需要检查 Try
对象是否成功,并根据结果进行处理。
返回值类型 Try<T>
select()
返回的 Future<Try<T>>
使用 Try<T>
来包装结果,这是因为最先完成的 Future 可能是成功的,也可能是失败的。使用 Try<T>
可以方便地处理这两种情况。你可以使用 resultTry.isSuccess()
和 resultTry.isException()
来检查结果类型,并使用 resultTry.value()
和 resultTry.exception()
来获取值或异常。
6.3 race()
:竞争多个 Future,返回最先完成的结果 (race()
: Racing Multiple Futures, Returning the First Result)
race()
操作与 select()
非常相似,它们都关注一组 Future
中最先完成的那个。race()
函数也接受一个 Future
的容器,并返回一个新的 Future<Try<T>>
。与 select()
的主要区别在于,race()
不区分成功和失败,它只返回第一个完成的 Future
的结果,无论是成功还是失败。
这意味着,如果一组 Future
中,有一个 Future 最先失败,race()
也会返回这个失败的 Future 的结果(包装在 Try<T>
中)。而 select()
只会选择第一个成功完成的 Future。如果所有 Future 都失败,select()
最终会返回一个失败的 Future,而 race()
则会返回第一个失败的 Future 的结果。
使用场景
race()
适用于以下场景:
① 快速失败机制:在某些情况下,你只需要知道一组任务中是否有任何一个快速失败,而不需要等待所有任务完成。race()
可以帮助你快速检测到第一个失败的任务。
② 熔断器模式:在微服务架构中,可以使用 race()
实现熔断器模式。当依赖的服务出现故障时,熔断器可以快速失败后续的请求,避免雪崩效应。
③ 性能测试:在性能测试中,你可能需要测试多个服务的响应速度,race()
可以帮助你快速获取第一个响应的服务的结果。
代码示例
1
#include <folly/Future.h>
2
#include <folly/Try.h>
3
#include <folly/executors/InlineExecutor.h>
4
#include <iostream>
5
#include <vector>
6
7
using namespace folly;
8
9
Future<std::string> racingTask(std::string name, int delayMs, bool shouldFail) {
10
return DelayedExecutor::schedule(std::chrono::milliseconds(delayMs), InlineExecutor::instance())
11
.thenValue([name, shouldFail](Unit) {
12
if (shouldFail) {
13
throw std::runtime_error(name + " task failed in race");
14
}
15
std::cout << name << " task completed in race." << std::endl;
16
return name + " race result";
17
});
18
}
19
20
int main() {
21
std::vector<Future<std::string>> futures;
22
futures.push_back(racingTask("Task X", 150, true)); // Task X will fail first
23
futures.push_back(racingTask("Task Y", 200, false));
24
futures.push_back(racingTask("Task Z", 100, false)); // Task Z will complete successfully but later than X's failure
25
26
auto racedFuture = race(futures);
27
28
racedFuture.thenValue([](Try<std::string> resultTry) {
29
if (resultTry.isSuccess()) {
30
std::cout << "First raced task success result: " << resultTry.value() << std::endl;
31
} else {
32
std::cerr << "First raced task failure result: " << resultTry.exception().what() << std::endl;
33
}
34
});
35
36
// Normally you would need to block to wait for the future to complete in a main function
37
// For demonstration purposes, we are using InlineExecutor which executes synchronously in this example.
38
return 0;
39
}
代码解释
① racingTask
函数与 fastTask
类似,模拟异步任务,可以设置延迟和是否失败。
② 在 main
函数中,Task X 设置为快速失败,Task Y 和 Task Z 都会成功完成,但 Task Z 的延迟最短。
③ 使用 race(futures)
竞争这些任务。由于 Task X 最先失败,racedFuture
会立即完成,并携带 Task X 的失败结果。
race()
与 select()
的选择
选择 race()
还是 select()
取决于你的具体需求:
① 如果你只关心第一个成功的结果,并且希望忽略失败的任务,那么应该使用 select()
。
② 如果你关心第一个完成的结果,无论是成功还是失败,并且需要快速响应,那么应该使用 race()
。
③ 如果你需要等待所有任务都完成,并且需要所有任务都成功才能继续,那么应该使用 collect()
。
6.4 andThen()
:在 Future 完成后执行另一个操作 (andThen()
: Executing Another Operation After Future Completion)
andThen()
是一个用于在现有 Future
完成后无条件执行另一个操作的组合操作。与 then()
系列方法(如 thenValue()
、thenError()
、thenTry()
)不同,andThen()
不关心前一个 Future
的结果是成功还是失败,它只确保在之前的 Future
完成后,无论结果如何,都会执行指定的后续操作。
andThen()
接受一个函数作为参数,这个函数不接受前一个 Future
的结果作为输入,而是返回一个新的 Future<Unit>
(或者 Future<void>
)。andThen()
返回的 Future
会在前一个 Future
和 andThen()
中指定的操作都完成后完成。最终 andThen()
返回的 Future 的结果类型与原始 Future 保持一致。
使用场景
andThen()
适用于以下场景:
① 资源清理:无论异步操作成功还是失败,都需要执行一些清理工作,例如释放资源、关闭连接等。
② 日志记录:在异步操作完成后,记录操作的完成状态,用于监控和审计。
③ 触发后续流程:在某个异步操作完成后,无论结果如何,都需要触发后续的流程,例如发送通知、更新状态等。
代码示例
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
5
using namespace folly;
6
7
Future<int> operation() {
8
return makeFuture(10); // Simulate an operation that returns 10
9
}
10
11
Future<Unit> cleanupTask() {
12
std::cout << "Cleanup task executed." << std::endl;
13
return makeFuture(); // Returns a Future<Unit> indicating completion
14
}
15
16
int main() {
17
auto future = operation();
18
19
auto futureWithCleanup = future.andThen([]() {
20
return cleanupTask();
21
});
22
23
futureWithCleanup.thenValue([](int result) {
24
std::cout << "Operation result: " << result << std::endl;
25
}).thenError([](const std::exception& e) {
26
std::cerr << "Operation failed: " << e.what() << std::endl;
27
});
28
29
// Normally you would need to block to wait for the future to complete in a main function
30
// For demonstration purposes, we are using InlineExecutor which executes synchronously in this example.
31
return 0;
32
}
代码解释
① operation
函数模拟一个异步操作,返回 Future<int>
。
② cleanupTask
函数模拟一个清理任务,返回 Future<Unit>
。
③ 使用 future.andThen([]() { return cleanupTask(); })
将清理任务添加到 operation
的 Future 链中。andThen
的 lambda 函数不接受任何参数,并返回 cleanupTask()
的 Future。
④ 无论 operation
成功还是失败,cleanupTask()
都会被执行。最终 futureWithCleanup
的结果类型仍然是 Future<int>
,与原始的 operation
Future 一致。
andThen()
与 then()
的区别
andThen()
和 then()
系列方法都是用于链式操作 Future,但它们有关键的区别:
① then()
系列方法(如 thenValue()
、thenError()
、thenTry()
)是条件执行的,它们根据前一个 Future
的结果(成功或失败)来决定是否执行后续操作,并且可以处理前一个 Future
的结果。
② andThen()
是无条件执行的,它不关心前一个 Future
的结果,只确保在之前的 Future
完成后执行后续操作。andThen()
的后续操作通常用于执行一些副作用,例如清理资源、记录日志等,而不是处理前一个 Future 的结果。
在选择使用 andThen()
还是 then()
系列方法时,你需要根据你的需求来决定:如果你需要根据前一个 Future
的结果来决定后续操作,或者需要处理前一个 Future
的结果,那么应该使用 then()
系列方法;如果你只需要在 Future 完成后执行一些清理或后续操作,而不需要关心前一个 Future
的结果,那么可以使用 andThen()
。
总结
本章介绍了 folly::Future
的四个重要的组合操作:collect()
、select()
、race()
和 andThen()
。这些操作为处理多个异步任务提供了强大的工具,可以帮助你构建更复杂、更健壮的异步应用。理解和掌握这些组合操作,对于深入理解和应用 folly::futures
库至关重要。
END_OF_CHAPTER
7. chapter 7: Future 的取消与超时 (Cancellation and Timeout of Future)
7.1 Future 的取消机制 (Cancellation Mechanism of Future)
在异步编程中,取消一个尚未完成的任务是一项重要的功能。folly::Future
提供了灵活且强大的取消机制,允许在不再需要任务结果时,或者任务执行时间过长时,优雅地停止任务的执行。取消操作不仅可以节省计算资源,还可以提高程序的响应性和效率。
7.1.1 Future::cancel()
:取消 Future (Future::cancel()
: Cancelling Future)
Future::cancel()
方法是取消 Future
的核心手段。当在一个 Future
对象上调用 cancel()
方法时,它会尝试将该 Future
标记为已取消状态,并尽力阻止与该 Future
相关的后续操作继续执行。
基本用法
要取消一个 Future
,首先需要获取到 Future
对象。通常,Future
对象是由 Promise
创建,或者通过 then()
等链式操作返回的。一旦拥有了 Future
对象,就可以直接调用其 cancel()
方法。
1
#include <folly/futures/Future.h>
2
#include <folly/futures/Promise.h>
3
#include <iostream>
4
#include <thread>
5
6
using namespace folly;
7
8
int main() {
9
Promise<int> promise;
10
Future<int> future = promise.getFuture();
11
12
// 启动一个线程模拟异步任务
13
std::thread task_thread([&promise]() {
14
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作
15
promise.setValue(42); // 设置 Future 的值
16
std::cout << "Task finished and set value." << std::endl;
17
});
18
19
// 主线程休眠 1 秒后取消 Future
20
std::this_thread::sleep_for(std::chrono::seconds(1));
21
future.cancel();
22
std::cout << "Future cancelled." << std::endl;
23
24
// 等待任务线程结束
25
task_thread.join();
26
27
// 检查 Future 的状态
28
if (future.isCancelled()) {
29
std::cout << "Future is cancelled." << std::endl;
30
} else if (future.isReady()) {
31
std::cout << "Future is ready." << std::endl;
32
}
33
34
return 0;
35
}
代码解释
① 首先,我们创建了一个 Promise<int>
和与其关联的 Future<int>
。
② 启动了一个新的线程 task_thread
来模拟一个耗时 2 秒的异步任务。在这个模拟任务中,线程休眠 2 秒后,会通过 promise.setValue(42)
设置 Future
的值。
③ 在主线程中,我们休眠 1 秒后调用 future.cancel()
来取消 Future
。
④ 最后,我们等待任务线程结束,并检查 Future
的状态。
运行结果分析
由于 future.cancel()
在任务线程设置值之前被调用,Future
会被标记为取消状态。即使任务线程后续尝试设置值,Future
的状态已经变为取消,后续的 then()
回调等操作将不会被执行。程序的输出结果会显示 "Future cancelled." 和 "Future is cancelled."。
注意事项
⚝ 尽力而为的取消 (Best-Effort Cancellation):Future::cancel()
是一种尽力而为的操作。它会尝试取消 Future
,但并不能保证立即停止底层任务的执行。如果异步任务已经开始执行并且无法中断(例如,某些系统调用),那么即使调用了 cancel()
,任务也可能会继续执行到完成。
⚝ 取消状态 (Cancelled State):一旦 Future
被成功取消,其状态会变为已取消 (isCancelled() == true
)。取消是一个最终状态,一旦 Future
进入取消状态,就不能再变为其他状态(例如,完成或异常)。
⚝ 取消后的操作:对于已取消的 Future
,尝试获取其值或注册回调通常不会执行,或者会抛出异常,具体行为取决于操作类型。例如,get()
方法会抛出 FutureCancelled
异常。
7.1.2 取消传播与协作 (Cancellation Propagation and Cooperation)
folly::Future
的取消机制支持取消传播(Cancellation Propagation)和取消协作(Cancellation Cooperation),这使得构建复杂的异步流程时,取消操作能够有效地传递和处理。
取消传播 (Cancellation Propagation)
取消传播指的是当一个 Future
被取消时,这个取消信号能够自动地传递到由该 Future
衍生出来的其他 Future
上。例如,当在一个 Future
上使用 then()
创建新的 Future
时,如果原始 Future
被取消,那么 then()
返回的 Future
也会自动被取消。
1
#include <folly/futures/Future.h>
2
#include <folly/futures/Promise.h>
3
#include <iostream>
4
#include <thread>
5
6
using namespace folly;
7
8
int main() {
9
Promise<int> promise;
10
Future<int> future1 = promise.getFuture();
11
12
// 使用 then() 创建新的 Future
13
Future<int> future2 = future1.thenValue([](int value) {
14
std::cout << "future1 completed with value: " << value << std::endl;
15
return value * 2;
16
});
17
18
// 主线程休眠 1 秒后取消 future1
19
std::this_thread::sleep_for(std::chrono::seconds(1));
20
future1.cancel();
21
std::cout << "future1 cancelled." << std::endl;
22
23
// 检查 future2 的状态
24
if (future2.isCancelled()) {
25
std::cout << "future2 is also cancelled due to propagation." << std::endl;
26
} else if (future2.isReady()) {
27
std::cout << "future2 is ready." << std::endl;
28
}
29
30
return 0;
31
}
代码解释
① 我们首先创建了一个 Promise<int>
和 Future<int> future1
。
② 然后,使用 future1.thenValue()
创建了新的 Future<int> future2
。future2
的操作依赖于 future1
的结果。
③ 在主线程中,我们休眠 1 秒后取消了 future1
。
④ 最后,我们检查 future2
的状态。
运行结果分析
由于取消传播机制,当 future1
被取消时,future2
也自动被取消。因此,thenValue
中的回调函数不会被执行,并且 future2.isCancelled()
返回 true
。程序的输出结果会显示 "future1 cancelled." 和 "future2 is also cancelled due to propagation."。
取消协作 (Cancellation Cooperation)
取消协作指的是异步任务本身需要主动检查取消状态,并在检测到取消信号时,主动停止执行并清理资源。folly::Future
的取消机制通过 CancellationCallback
和 CancellationToken
来实现取消协作。
CancellationCallback
和 CancellationToken
当创建一个 Promise
对象时,可以关联一个 CancellationToken
。CancellationToken
可以被用来注册 CancellationCallback
,当与 CancellationToken
关联的 Promise
的 Future
被取消时,所有注册的回调函数都会被执行。
1
#include <folly/futures/Future.h>
2
#include <folly/futures/Promise.h>
3
#include <folly/CancellationToken.h>
4
#include <iostream>
5
#include <thread>
6
#include <chrono>
7
8
using namespace folly;
9
10
int main() {
11
CancellationTokenSource cts;
12
CancellationToken token = cts.getToken();
13
Promise<int> promise(token); // Promise 关联 CancellationToken
14
Future<int> future = promise.getFuture();
15
16
// 注册取消回调函数
17
token.registerCallback([]() {
18
std::cout << "Cancellation callback executed." << std::endl;
19
// 执行清理操作,例如释放资源
20
});
21
22
// 启动一个线程模拟可取消的异步任务
23
std::thread task_thread([&promise, &token]() {
24
for (int i = 0; i < 5; ++i) {
25
if (token.isCancelled()) { // 检查取消状态
26
std::cout << "Task cancelled internally." << std::endl;
27
return; // 主动停止任务执行
28
}
29
std::cout << "Task is running... step " << i + 1 << std::endl;
30
std::this_thread::sleep_for(std::chrono::seconds(1));
31
}
32
promise.setValue(100); // 设置 Future 的值
33
std::cout << "Task finished and set value." << std::endl;
34
});
35
36
// 主线程休眠 2 秒后取消 Future
37
std::this_thread::sleep_for(std::chrono::seconds(2));
38
cts.cancel(); // 通过 CancellationTokenSource 取消
39
std::cout << "Future cancelled externally." << std::endl;
40
41
// 等待任务线程结束
42
task_thread.join();
43
44
// 检查 Future 的状态
45
if (future.isCancelled()) {
46
std::cout << "Future is cancelled." << std::endl;
47
} else if (future.isReady()) {
48
std::cout << "Future is ready." << std::endl;
49
}
50
51
return 0;
52
}
代码解释
① 我们创建了一个 CancellationTokenSource
和 CancellationToken
。Promise<int> promise
在创建时关联了 token
。
② 使用 token.registerCallback()
注册了一个取消回调函数。当 Future
被取消时,这个回调函数会被执行。
③ 在 task_thread
中,异步任务在循环的每一步都检查 token.isCancelled()
。如果检测到取消信号,任务会主动停止执行并返回。
④ 主线程休眠 2 秒后,通过 cts.cancel()
取消 Future
。cts.cancel()
会触发与 token
关联的所有取消回调函数。
运行结果分析
由于主线程在 2 秒后取消了 Future
,任务线程在执行到第三步时会检测到取消信号,并输出 "Task cancelled internally." 后停止执行。同时,注册的取消回调函数也会被执行,输出 "Cancellation callback executed."。程序的输出结果会包含 "Future cancelled externally.", "Task cancelled internally.", "Cancellation callback executed." 和 "Future is cancelled."。
取消传播与协作的结合
取消传播和取消协作可以结合使用,构建更健壮和灵活的异步取消机制。取消传播确保取消信号能够自动传递到相关的 Future
链上,而取消协作则允许异步任务在内部主动响应取消信号,进行资源清理和优雅退出。
7.2 Future 的超时处理 (Timeout Handling of Future)
在异步操作中,设置超时时间是非常重要的。如果一个异步任务执行时间过长,超过了预期的响应时间,我们可能需要放弃等待,并认为任务超时。folly::Future
提供了 within()
方法来方便地实现超时处理。
7.2.1 within()
:设置 Future 的超时时间 (within()
: Setting Timeout for Future)
Future::within()
方法可以为一个 Future
设置超时时间。如果在指定的时间内 Future
没有完成(既没有设置值,也没有设置异常),within()
返回的新的 Future
将会以 TimeoutException
异常完成。
基本用法
1
#include <folly/futures/Future.h>
2
#include <folly/futures/Promise.h>
3
#include <folly/exception/TimeoutException.h>
4
#include <iostream>
5
#include <thread>
6
#include <chrono>
7
8
using namespace folly;
9
10
int main() {
11
Promise<int> promise;
12
Future<int> future = promise.getFuture();
13
14
// 设置 1 秒超时
15
Future<int> timeoutFuture = future.within(std::chrono::seconds(1));
16
17
// 启动一个线程模拟耗时 2 秒的异步任务
18
std::thread task_thread([&promise]() {
19
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作
20
promise.setValue(42); // 设置 Future 的值
21
std::cout << "Task finished and set value." << std::endl;
22
});
23
24
Try<int> result = timeoutFuture.getTry(); // 同步等待结果
25
26
if (result.hasValue()) {
27
std::cout << "Future completed with value: " << result.value() << std::endl;
28
} else if (result.hasException()) {
29
try {
30
result.throwException(); // 抛出异常
31
} catch (const TimeoutException& e) {
32
std::cerr << "TimeoutException caught: " << e.what() << std::endl;
33
} catch (const std::exception& e) {
34
std::cerr << "Exception caught: " << e.what() << std::endl;
35
}
36
}
37
38
task_thread.join();
39
return 0;
40
}
代码解释
① 我们创建了一个 Promise<int>
和 Future<int> future
。
② 使用 future.within(std::chrono::seconds(1))
为 future
设置了 1 秒的超时时间,返回新的 Future<int> timeoutFuture
。
③ 启动一个线程 task_thread
模拟耗时 2 秒的异步任务。
④ 主线程通过 timeoutFuture.getTry()
同步等待 timeoutFuture
的结果。getTry()
返回 Try<T>
对象,可以方便地检查结果是值还是异常。
⑤ 如果 result.hasException()
为真,我们尝试抛出异常,并捕获 TimeoutException
和其他标准异常。
运行结果分析
由于异步任务耗时 2 秒,超过了 within()
设置的 1 秒超时时间,timeoutFuture
会在 1 秒后以 TimeoutException
异常完成。程序会捕获 TimeoutException
并输出 "TimeoutException caught: Operation timed out."。
超时时间设置
within()
方法接受一个时间段作为参数,可以使用 std::chrono
库提供的各种时间单位,例如 std::chrono::milliseconds
, std::chrono::microseconds
等。
1
// 设置 500 毫秒超时
2
Future<int> timeoutFutureMs = future.within(std::chrono::milliseconds(500));
3
4
// 设置 2.5 秒超时
5
Future<int> timeoutFutureFloatSec = future.within(std::chrono::duration<double>(2.5));
7.2.2 超时异常处理 (Timeout Exception Handling)
当 Future
因为超时而完成时,它会携带 folly::TimeoutException
异常。在处理超时 Future
时,需要捕获并处理 TimeoutException
异常。
捕获 TimeoutException
在 then()
, getTry()
, get()
等方法处理 Future
结果时,可以通过 catch
语句捕获 TimeoutException
异常,并进行相应的处理,例如记录日志、返回默认值或重试操作。
1
#include <folly/futures/Future.h>
2
#include <folly/futures/Promise.h>
3
#include <folly/exception/TimeoutException.h>
4
#include <iostream>
5
#include <thread>
6
#include <chrono>
7
8
using namespace folly;
9
10
int main() {
11
Promise<int> promise;
12
Future<int> future = promise.getFuture();
13
14
Future<int> timeoutFuture = future.within(std::chrono::seconds(1));
15
16
timeoutFuture.thenValue([](int value) {
17
std::cout << "Value received: " << value << std::endl;
18
}).thenError<TimeoutException>([](const TimeoutException& e) {
19
std::cerr << "Timeout occurred: " << e.what() << std::endl;
20
// 处理超时逻辑,例如返回默认值,重试等
21
return -1; // 返回默认值
22
}).then([](Try<int> result) {
23
if (result.hasValue()) {
24
std::cout << "Final result: " << result.value() << std::endl;
25
} else if (result.hasException()) {
26
std::cerr << "Final exception: " << result.exception().what() << std::endl;
27
}
28
});
29
30
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作
31
32
return 0;
33
}
代码解释
① 我们使用 future.within(std::chrono::seconds(1))
设置超时。
② 使用 thenValue()
处理正常值,thenError<TimeoutException>()
专门处理 TimeoutException
异常。在 thenError<TimeoutException>()
中,我们捕获 TimeoutException
,输出错误信息,并返回一个默认值 -1
。
③ 最后的 then()
接收 Try<int>
对象,统一处理最终结果,包括正常值和异常(这里实际上已经被 thenError
处理成了默认值)。
运行结果分析
由于超时发生,thenError<TimeoutException>()
中的回调函数会被执行,输出 "Timeout occurred: Operation timed out.",并返回默认值 -1
。最终,then()
中的回调函数会接收到默认值 -1
,并输出 "Final result: -1"。
超时处理的最佳实践
⚝ 合理设置超时时间:超时时间的设置应该根据具体的应用场景和任务的预期执行时间来确定。超时时间设置过短可能会导致任务频繁超时,而设置过长则可能无法及时响应问题。
⚝ 提供超时处理逻辑:在捕获 TimeoutException
后,应该提供合理的处理逻辑,例如记录日志、返回默认值、重试操作、或者取消相关的操作链。
⚝ 结合取消机制:超时处理通常与取消机制结合使用。当 Future
超时时,可以同时取消底层的异步任务,以节省资源。
通过 Future::cancel()
和 Future::within()
,folly::Future
提供了完善的取消和超时处理机制,使得开发者能够构建更健壮、更可靠的异步应用程序。合理地运用取消和超时机制,可以有效地管理异步任务的生命周期,提高程序的性能和用户体验。
END_OF_CHAPTER
8. chapter 8: Future 的异常处理 (Exception Handling of Future)
8.1 异常的传播与捕获 (Exception Propagation and Catching)
在异步编程中,异常处理是一个至关重要的环节。与同步代码不同,异步操作的结果在未来某个时间点才能获得,因此,当异步操作发生异常时,如何有效地传播和捕获这些异常,就成为了保证程序健壮性的关键。folly::Future
提供了一套完善的机制来处理异步操作中的异常,确保异常能够被正确地传播到调用链的合适位置,并允许开发者灵活地捕获和处理这些异常。
异常的传播 (Exception Propagation)
当一个 Future
代表的异步操作失败并抛出异常时,这个异常会被封装在 Future
对象中。如果这个 Future
对象被作为链式操作(例如通过 then()
, map()
, flatMap()
等方法)的一部分,异常会自动沿着 Future
链向下传播。这意味着,如果链中的某个环节的 Future
产生了异常,后续的链式操作默认情况下不会被执行,异常会一直传递到链的末端,或者直到遇到显式的异常处理逻辑。
这种异常传播机制的设计,简化了异步代码的错误处理流程。开发者无需在每个异步操作后都显式地检查错误,只需要在链的合适位置设置异常处理逻辑即可。
异常的捕获 (Exception Catching)
folly::Future
提供了多种方法来捕获和处理异常,最常用的方法包括:
① then()
方法的异常处理回调:then()
方法可以接受两个回调函数,第一个用于处理 Future
成功完成的值,第二个用于处理 Future
抛出的异常。通过提供异常处理回调,可以在 Future
链的中间环节捕获并处理异常,阻止异常继续传播。
② catch()
和 catchError()
方法:catch()
和 catchError()
方法专门用于捕获和处理特定类型的异常。它们允许开发者针对不同类型的异常,提供不同的处理逻辑。
③ recover()
和 recoverWith()
方法:recover()
和 recoverWith()
方法不仅可以捕获异常,还允许开发者从异常中恢复,返回一个默认值或者一个新的 Future
,从而使 Future
链能够继续执行下去。
示例代码:异常传播
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
#include <stdexcept>
5
6
using namespace folly;
7
8
Future<int> asyncOperation() {
9
// 模拟一个可能抛出异常的异步操作
10
return makeFuture<int>([]() -> int {
11
throw std::runtime_error("Async operation failed!");
12
return 42; // 这行代码不会被执行
13
}());
14
}
15
16
int main() {
17
asyncOperation()
18
.thenValue([](int result) {
19
std::cout << "Result: " << result << std::endl; // 这段代码不会被执行
20
})
21
.thenError([](const std::runtime_error& e) {
22
std::cerr << "Caught exception: " << e.what() << std::endl;
23
})
24
.get(); // 同步等待 Future 完成
25
26
return 0;
27
}
在这个例子中,asyncOperation()
函数模拟了一个会抛出 std::runtime_error
异常的异步操作。当 asyncOperation()
返回的 Future
抛出异常后,.thenValue()
中的成功回调不会被执行,异常会传播到 .thenError()
中定义的异常处理回调,最终在控制台输出错误信息 "Caught exception: Async operation failed!"。
总结
folly::Future
的异常传播机制简化了异步编程中的错误处理,开发者可以通过 thenError()
, catch()
, catchError()
, recover()
, recoverWith()
等方法,灵活地捕获和处理不同类型的异常,保证程序的健壮性和可靠性。理解异常的传播与捕获机制,是编写高质量异步代码的基础。
8.2 catch()
和 catchError()
:捕获特定类型的异常 (catch()
and catchError()
: Catching Specific Exception Types)
在实际的异步编程中,我们可能需要根据异常的类型采取不同的处理策略。folly::Future
提供了 catch()
和 catchError()
方法,用于捕获特定类型的异常,并执行相应的处理逻辑。这两个方法允许开发者更精细地控制异常处理流程,提高代码的灵活性和可维护性。
catch()
方法
catch()
方法接受一个函数对象作为参数,这个函数对象会被调用来处理 Future
中抛出的异常。catch()
方法的特点是,它可以捕获任何类型的异常。其函数签名通常类似于:
1
template <typename ExceptionType, typename Handler>
2
auto catch(Handler handler);
其中,ExceptionType
是要捕获的异常类型,Handler
是一个函数对象,用于处理捕获到的异常。如果 Future
抛出的异常类型与 ExceptionType
匹配(或者可以隐式转换为 ExceptionType
),则 handler
会被调用。catch()
方法返回一个新的 Future
,如果异常被成功处理,新的 Future
可以返回一个值,或者继续抛出异常(如果处理逻辑本身也抛出了异常)。
catchError()
方法
catchError()
方法是 catch()
方法的别名,它们在功能上完全相同。在 folly
库中,catchError()
更多地被推荐使用,因为它更清晰地表达了“捕获错误”的意图。
示例代码:使用 catch()
和 catchError()
捕获特定异常
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
#include <stdexcept>
5
#include <string>
6
7
using namespace folly;
8
9
Future<std::string> fetchData() {
10
// 模拟一个可能抛出不同类型异常的异步操作
11
return makeFuture<std::string>([]() -> std::string {
12
int errorCode = 500; // 假设返回 500 代表服务器错误
13
if (errorCode == 404) {
14
throw std::runtime_error("Resource not found (404)");
15
} else if (errorCode == 500) {
16
throw std::domain_error("Internal server error (500)");
17
} else {
18
return "Data fetched successfully";
19
}
20
}());
21
}
22
23
int main() {
24
fetchData()
25
.catchError<std::runtime_error>([](const std::runtime_error& e) {
26
std::cerr << "Caught runtime error: " << e.what() << std::endl;
27
return std::string("Default data for runtime error"); // 从异常中恢复,返回默认值
28
})
29
.catchError<std::domain_error>([](const std::domain_error& e) {
30
std::cerr << "Caught domain error: " << e.what() << std::endl;
31
return std::string("Default data for domain error"); // 从异常中恢复,返回默认值
32
})
33
.thenValue([](const std::string& data) {
34
std::cout << "Data: " << data << std::endl;
35
})
36
.get();
37
38
return 0;
39
}
在这个例子中,fetchData()
函数模拟了一个异步数据获取操作,它可能会抛出 std::runtime_error
(404 错误) 或 std::domain_error
(500 错误)。
代码中使用了两个 .catchError<>()
方法,分别捕获 std::runtime_error
和 std::domain_error
类型的异常。如果 fetchData()
抛出 std::runtime_error
,则第一个 .catchError<>()
的处理函数会被调用,输出 "Caught runtime error: Resource not found (404)",并返回一个默认字符串 "Default data for runtime error"。如果抛出 std::domain_error
,则第二个 .catchError<>()
的处理函数会被调用,输出 "Caught domain error: Internal server error (500)",并返回 "Default data for domain error"。
如果 fetchData()
成功返回数据,或者异常被 .catchError<>()
处理并返回了默认值,.thenValue()
中的成功回调最终会被执行,输出相应的数据。
总结
catch()
和 catchError()
方法是 folly::Future
提供的强大的异常处理工具,它们允许开发者根据异常的类型进行精细化的处理。通过使用 catch()
或 catchError()
,可以提高异步代码的健壮性和可维护性,更好地应对各种异常情况。在实际应用中,根据业务逻辑和错误类型,合理地使用 catch()
和 catchError()
,可以有效地提升程序的容错能力。
8.3 recover()
和 recoverWith()
:从异常中恢复 (recover()
and recoverWith()
: Recovering from Exception)
除了捕获和处理异常,folly::Future
还提供了从异常中恢复的机制。recover()
和 recoverWith()
方法允许开发者在 Future
链中遇到异常时,提供一个备选的值或者一个新的 Future
,从而使整个异步流程能够继续执行下去,而不是因为异常而中断。
recover()
方法
recover()
方法接受一个函数对象作为参数,这个函数对象会在 Future
抛出异常时被调用。recover()
方法的函数对象需要返回一个值,这个值会被作为新的 Future
的结果,从而“恢复”了之前的异常状态。其函数签名通常类似于:
1
template <typename Handler>
2
auto recover(Handler handler);
其中,Handler
是一个函数对象,用于处理异常并返回一个恢复值。recover()
方法返回一个新的 Future
,这个新的 Future
要么包含 handler
返回的恢复值(如果原始 Future
抛出了异常),要么包含原始 Future
的成功结果(如果原始 Future
成功完成)。
recoverWith()
方法
recoverWith()
方法与 recover()
方法类似,也用于从异常中恢复。但 recoverWith()
的函数对象需要返回一个新的 Future
,而不是一个直接的值。这使得 recoverWith()
可以在异常发生时,启动另一个异步操作来作为恢复手段。其函数签名通常类似于:
1
template <typename Handler>
2
auto recoverWith(Handler handler);
其中,Handler
是一个函数对象,用于处理异常并返回一个新的 Future
。recoverWith()
方法返回一个新的 Future
,这个新的 Future
要么是 handler
返回的 Future
(如果原始 Future
抛出了异常),要么是原始 Future
本身(如果原始 Future
成功完成)。
示例代码:使用 recover()
和 recoverWith()
从异常中恢复
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
#include <stdexcept>
5
#include <string>
6
7
using namespace folly;
8
9
Future<int> riskyOperation() {
10
// 模拟一个可能失败的异步操作
11
return makeFuture<int>([]() -> int {
12
if (rand() % 2 == 0) {
13
throw std::runtime_error("Risky operation failed!");
14
}
15
return 100;
16
}());
17
}
18
19
Future<int> fallbackOperation() {
20
// 备选的异步操作
21
return makeFuture<int>(200);
22
}
23
24
int main() {
25
srand(time(0)); // 初始化随机数种子
26
27
riskyOperation()
28
.recover([](const std::runtime_error& e) {
29
std::cerr << "Recovered from exception: " << e.what() << ", using default value." << std::endl;
30
return -1; // 使用默认值 -1 恢复
31
})
32
.thenValue([](int result) {
33
std::cout << "Result after recover (using recover()): " << result << std::endl;
34
})
35
.get();
36
37
riskyOperation()
38
.recoverWith([](const std::runtime_error& e) {
39
std::cerr << "Recovered from exception: " << e.what() << ", using fallback operation." << std::endl;
40
return fallbackOperation(); // 使用备选的异步操作恢复
41
})
42
.thenValue([](int result) {
43
std::cout << "Result after recover (using recoverWith()): " << result << std::endl;
44
})
45
.get();
46
47
return 0;
48
}
在这个例子中,riskyOperation()
函数模拟了一个有风险的异步操作,它有 50% 的概率抛出 std::runtime_error
异常。fallbackOperation()
函数是一个备选的异步操作,用于在 riskyOperation()
失败时提供一个替代结果。
第一个 Future
链使用了 .recover()
方法。如果 riskyOperation()
抛出异常,.recover()
的处理函数会被调用,输出错误信息,并返回默认值 -1
。最终 .thenValue()
会接收到 -1
并输出 "Result after recover (using recover()): -1"。如果 riskyOperation()
成功,.recover()
不会被调用,.thenValue()
会接收到 riskyOperation()
的结果 (100) 并输出 "Result after recover (using recover()): 100"。
第二个 Future
链使用了 .recoverWith()
方法。如果 riskyOperation()
抛出异常,.recoverWith()
的处理函数会被调用,输出错误信息,并返回 fallbackOperation()
返回的 Future
。最终 .thenValue()
会接收到 fallbackOperation()
的结果 (200) 并输出 "Result after recover (using recoverWith()): 200"。如果 riskyOperation()
成功,.recoverWith()
不会被调用,.thenValue()
会接收到 riskyOperation()
的结果 (100) 并输出 "Result after recover (using recoverWith()): 100"。
总结
recover()
和 recoverWith()
方法为 folly::Future
提供了强大的异常恢复能力。recover()
适用于在异常发生时提供一个静态的默认值进行恢复的场景,而 recoverWith()
更适用于需要启动另一个异步操作来作为恢复手段的场景。合理地使用 recover()
和 recoverWith()
可以增强异步程序的容错性,使其在面对错误时能够更加优雅地降级和恢复,提升用户体验。
8.4 异常处理的最佳实践 (Best Practices for Exception Handling)
在异步编程中使用 folly::Future
进行异常处理时,遵循一些最佳实践可以帮助我们编写更健壮、可维护和易于理解的代码。以下是一些关键的实践建议:
① 尽早处理异常,避免异常无限传播:虽然 Future
的异常传播机制很方便,但过度依赖异常传播可能会使错误定位变得困难。最佳实践是在 Future
链的合适位置尽早处理异常,例如在模块边界或关键业务逻辑处。这样可以更清晰地界定错误的影响范围,并采取相应的补救措施。
② 使用 catchError()
或 catch()
捕获特定类型的异常:根据异常类型进行不同的处理是良好的编程习惯。使用 catchError<ExceptionType>()
或 catch<ExceptionType>()
可以精确地捕获特定类型的异常,并执行相应的处理逻辑。避免使用通用的异常捕获,除非确实需要对所有类型的异常进行统一处理。
③ 合理使用 recover()
和 recoverWith()
进行异常恢复:当异步操作失败时,考虑是否可以通过提供默认值或执行备选操作来恢复。recover()
和 recoverWith()
方法是实现异常恢复的有力工具。但需要谨慎使用恢复机制,确保恢复操作不会掩盖潜在的严重错误,并且恢复后的状态仍然是可接受的。
④ 在必要时重新抛出异常:在异常处理函数中,有时需要根据情况决定是否将异常继续传播。如果当前的异常处理逻辑无法完全解决问题,或者需要将异常传递给上层调用者处理,可以使用 std::rethrow_exception()
或抛出一个新的异常来重新抛出。
⑤ 记录详细的错误日志:在异常处理函数中,务必记录详细的错误日志,包括异常类型、错误信息、发生时间、上下文信息等。这些日志对于错误诊断和问题排查至关重要。可以使用 folly::Logger
或其他日志库来记录日志。
⑥ 避免在异常处理函数中执行耗时操作:异常处理函数应该尽可能快速地执行完成,避免在其中执行耗时操作,例如复杂的计算、网络请求等。如果需要在异常处理时执行耗时操作,可以考虑将其放到后台线程或使用异步方式执行,避免阻塞当前的 Future
链。
⑦ 测试异常处理逻辑:编写单元测试来验证异常处理逻辑的正确性。模拟各种异常场景,确保异常能够被正确地捕获、处理和恢复。可以使用 folly::test::FutureTestUtils
等工具来辅助测试 Future
的异常处理。
示例代码:异常处理最佳实践
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <folly/logging/xlog.h>
4
#include <iostream>
5
#include <stdexcept>
6
#include <string>
7
8
using namespace folly;
9
10
Future<std::string> fetchDataFromRemote() {
11
// 模拟从远程服务获取数据的异步操作,可能抛出网络异常
12
return makeFuture<std::string>([]() -> std::string {
13
if (rand() % 3 == 0) {
14
throw std::system_error(std::make_error_code(std::errc::network_unreachable), "Network error");
15
} else if (rand() % 3 == 1) {
16
throw std::runtime_error("Data format error");
17
}
18
return "Data from remote service";
19
}());
20
}
21
22
Future<std::string> processData(std::string data) {
23
// 模拟数据处理操作
24
return makeFuture(data + " processed");
25
}
26
27
int main() {
28
srand(time(0));
29
30
fetchDataFromRemote()
31
.catchError<std::system_error>([](const std::system_error& e) {
32
XLOG(ERR) << "Network error occurred: " << e.what() << ", code: " << e.code();
33
return std::string("Default data due to network issue"); // 异常恢复,提供默认数据
34
})
35
.thenValue([](std::string data) {
36
return processData(data); // 继续链式操作
37
})
38
.catchError<std::runtime_error>([](const std::runtime_error& e) {
39
XLOG(ERR) << "Data processing error: " << e.what();
40
throw; // 重新抛出异常,传递给上层调用者处理
41
})
42
.thenValue([](std::string result) {
43
std::cout << "Final result: " << result << std::endl;
44
})
45
.thenError([](const std::exception& e) {
46
std::cerr << "Unhandled exception: " << e.what() << std::endl; // 最终的未处理异常捕获
47
})
48
.get();
49
50
return 0;
51
}
在这个例子中,我们展示了一些异常处理的最佳实践:
⚝ 尽早处理特定异常:使用 .catchError<std::system_error>()
捕获网络异常,并提供默认数据进行恢复。
⚝ 记录详细日志:在异常处理函数中使用 XLOG(ERR)
记录错误日志,方便问题排查。
⚝ 重新抛出异常:使用 throw;
在 .catchError<std::runtime_error>()
中重新抛出数据处理异常,将异常传递给上层处理。
⚝ 最终的未处理异常捕获:使用 .thenError([](const std::exception& e) {})
在 Future
链的末端捕获所有未处理的异常,保证程序不会因为未处理异常而崩溃。
总结
遵循这些最佳实践,可以帮助开发者在使用 folly::Future
进行异步编程时,编写出更加健壮、可靠和易于维护的代码。合理的异常处理策略是构建高质量异步应用的关键组成部分。
END_OF_CHAPTER
9. chapter 9: Future 与线程模型 (Future and Threading Model)
9.1 folly::Executor
接口 ( folly::Executor
Interface)
在 folly/futures
库中,folly::Executor
接口扮演着至关重要的角色,它是连接异步操作与具体执行线程之间的桥梁。理解 Executor
接口对于掌握 Future
的线程模型至关重要。
Executor
接口的核心职责是解耦异步任务的提交与执行。 换句话说,当你创建一个异步任务(例如,通过 then()
链式操作添加到 Future
上的回调函数)时,你并不直接指定这个任务将在哪个线程上运行。相反,你将这个任务提交给一个 Executor
,由 Executor
负责决定任务的具体执行方式和执行线程。这种设计模式提供了极大的灵活性和可配置性,允许开发者根据不同的应用场景和性能需求,选择合适的执行策略。
folly::Executor
是一个抽象基类,定义了执行任务的基本接口。其最核心的方法是 schedule(Func func)
。
1
class Executor {
2
public:
3
virtual ~Executor() = default;
4
5
virtual void schedule(Func func) = 0;
6
7
// ... 其他方法 ...
8
};
其中,Func
是一个可调用对象(Callable Object),例如函数对象、Lambda 表达式、或者 std::function
。schedule
方法接受一个 Func
对象作为参数,并将该对象代表的任务提交给 Executor
执行。Executor
的具体实现类负责决定何时以及在哪个线程上执行这个任务。
Executor
接口的主要作用可以归纳为:
① 任务调度 (Task Scheduling):Executor
负责接收提交的任务,并将其放入待执行队列中。具体的调度策略由 Executor
的实现类决定。例如,某些 Executor
可能会立即在当前线程执行任务(内联执行),而另一些 Executor
则会将任务放入线程池队列,等待线程池中的线程来执行。
② 线程管理 (Thread Management):Executor
隐藏了底层的线程管理细节。开发者无需直接创建和管理线程,只需要通过 Executor
提交任务,Executor
会负责任务在线程上的分配和执行。这大大简化了多线程编程的复杂性。
③ 执行策略配置 (Execution Policy Configuration):通过选择不同的 Executor
实现类,可以灵活地配置异步任务的执行策略。例如,可以使用 ThreadPoolExecutor
来利用线程池提高并发性能,或者使用 InlineExecutor
在特定场景下进行内联执行以减少线程切换开销。
④ 资源管理 (Resource Management):某些 Executor
实现类(如 ThreadPoolExecutor
和 IOThreadPoolExecutor
)还负责管理线程资源,例如线程的创建、销毁、复用等。这有助于更有效地利用系统资源,并避免资源泄漏等问题。
总结来说,folly::Executor
接口是 folly/futures
库线程模型的核心抽象。它通过解耦任务提交和执行,提供了灵活、可配置、且易于管理的方式来处理异步任务的线程执行。理解 Executor
接口是深入理解 folly::Future
线程模型的关键第一步。
9.2 常见的 Executor
实现 (Common Executor
Implementations)
folly
库提供了多种 Executor
接口的实现,以满足不同场景下的需求。 了解这些常见的 Executor
实现,可以帮助我们根据实际情况选择最合适的执行策略。
9.2.1 InlineExecutor
(内联执行器)
InlineExecutor
是最简单的一种 Executor
实现。顾名思义,InlineExecutor
会立即在当前线程内联执行提交给它的任务。这意味着当调用 executor->schedule(func)
时,func
会被直接调用,并且在 schedule
方法返回之前执行完成。
1
#include <folly/executors/InlineExecutor.h>
2
#include <iostream>
3
4
int main() {
5
folly::InlineExecutor executor;
6
7
std::cout << "Before schedule" << std::endl;
8
9
executor.schedule([] {
10
std::cout << "Inside scheduled task" << std::endl;
11
});
12
13
std::cout << "After schedule" << std::endl;
14
15
return 0;
16
}
输出结果:
1
Before schedule
2
Inside scheduled task
3
After schedule
从输出结果可以看出,"Inside scheduled task" 是在 "Before schedule" 和 "After schedule" 之间打印的,这表明 Lambda 表达式 [] { std::cout << "Inside scheduled task" << std::endl; }
是在 executor.schedule()
方法调用期间立即执行的。
InlineExecutor
的特点:
① 同步执行 (Synchronous Execution):任务提交和执行发生在同一个线程,是同步的。
② 无线程切换开销 (No Thread Switching Overhead):由于任务在当前线程执行,因此没有线程切换的开销,性能很高。
③ 简单高效 (Simple and Efficient):实现简单,执行效率高,适用于对延迟非常敏感且任务执行时间很短的场景。
④ 可能导致栈溢出 (Potential Stack Overflow):如果链式调用的异步任务过多,并且都使用 InlineExecutor
执行,可能会导致调用栈过深,引发栈溢出。
⑤ 不适合耗时操作 (Not Suitable for Time-Consuming Operations):由于会阻塞当前线程,InlineExecutor
不适合执行耗时的操作,否则会影响当前线程的响应性。
适用场景:
⚝ 单元测试 (Unit Testing):在单元测试中,为了方便调试和验证,可以使用 InlineExecutor
同步执行异步任务。
⚝ 对延迟极其敏感的短小任务 (Extremely Latency-Sensitive Short Tasks):例如,某些对性能要求极高的回调函数,可以考虑使用 InlineExecutor
以减少延迟。
⚝ 某些特定场景下的性能优化 (Performance Optimization in Specific Scenarios):在某些特定的性能优化场景下,例如已知任务执行时间非常短,且线程切换开销不可接受时,可以考虑使用 InlineExecutor
。
总而言之,InlineExecutor
是一种轻量级、高效的 Executor
实现,适用于对延迟敏感且任务执行时间短的场景。但需要注意其同步执行的特性,避免在耗时操作中使用,并注意潜在的栈溢出风险。
9.2.2 ThreadPoolExecutor
(线程池执行器)
ThreadPoolExecutor
是一个基于线程池的 Executor
实现,它维护着一个线程池来执行提交给它的任务。线程池可以有效地复用线程,减少线程创建和销毁的开销,提高并发性能。
1
#include <folly/executors/ThreadPoolExecutor.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
#include <thread>
5
6
int main() {
7
// 创建一个固定大小为 4 的线程池
8
auto executor = folly::ThreadPoolExecutor::newFixedThreadPool(4);
9
10
std::cout << "Main thread ID: " << std::this_thread::get_id() << std::endl;
11
12
for (int i = 0; i < 5; ++i) {
13
executor->schedule([i] {
14
std::cout << "Task " << i << " running on thread ID: " << std::this_thread::get_id() << std::endl;
15
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟耗时操作
16
});
17
}
18
19
// 等待线程池中的所有任务完成
20
executor->join();
21
std::cout << "All tasks completed." << std::endl;
22
23
return 0;
24
}
可能的输出结果 (线程 ID 可能每次运行都不同):
1
Main thread ID: 140735718993792
2
Task 0 running on thread ID: 140735718989568
3
Task 1 running on thread ID: 140735718989568
4
Task 2 running on thread ID: 140735718985344
5
Task 3 running on thread ID: 140735718981120
6
Task 4 running on thread ID: 140735718981120
7
All tasks completed.
从输出结果可以看出:
① 任务是在不同的线程上执行的,线程 ID 与主线程 ID 不同。
② 线程 ID 有重复,例如 Task 0 和 Task 1 在同一个线程上执行,Task 3 和 Task 4 在同一个线程上执行,这表明线程被复用了。
③ "All tasks completed." 是在所有任务执行完成后才打印的,executor->join()
确保了主线程等待所有线程池中的任务完成。
ThreadPoolExecutor
的特点:
① 异步执行 (Asynchronous Execution):任务提交和执行发生在不同的线程,是异步的。
② 线程池管理 (Thread Pool Management):内部维护一个线程池,负责线程的创建、销毁和复用,减少线程管理开销。
③ 并发执行 (Concurrent Execution):可以并发执行多个任务,提高系统的吞吐量。
④ 可配置性 (Configurable):可以配置线程池的大小、线程工厂、拒绝策略等参数,以满足不同的需求。
⑤ 适用于 CPU 密集型和 I/O 密集型任务 (Suitable for CPU-Bound and I/O-Bound Tasks):线程池可以有效地处理 CPU 密集型和 I/O 密集型任务,提高系统的并发性能。
适用场景:
⚝ 通用异步任务执行 (General Asynchronous Task Execution):ThreadPoolExecutor
是最常用的 Executor
实现之一,适用于大多数需要异步执行任务的场景。
⚝ CPU 密集型任务 (CPU-Bound Tasks):对于 CPU 密集型任务,可以使用线程池来充分利用多核 CPU 的计算能力。
⚝ I/O 密集型任务 (I/O-Bound Tasks):对于 I/O 密集型任务,线程池可以提高并发处理能力,例如网络请求处理、文件 I/O 操作等。
⚝ 需要限制并发度的场景 (Scenarios Requiring Concurrency Control):可以通过配置线程池的大小来限制系统的并发度,防止资源过度消耗。
ThreadPoolExecutor
提供了多种创建线程池的方式,例如:
⚝ newFixedThreadPool(threads)
:创建固定大小的线程池,线程池中始终保持 threads
个线程。
⚝ newCachedThreadPool()
:创建可缓存的线程池,线程池的大小可以动态调整,空闲线程会被回收,新任务到来时会创建新线程,适用于任务数量波动较大的场景。
⚝ newSingleThreadExecutor()
:创建单线程的线程池,所有任务都在同一个线程中顺序执行,适用于需要保证任务顺序执行的场景。
总结来说,ThreadPoolExecutor
是一种功能强大、应用广泛的 Executor
实现,适用于各种需要异步并发执行任务的场景。通过合理配置线程池参数,可以有效地提高系统的并发性能和资源利用率。
9.2.3 IOThreadPoolExecutor
(IO 线程池执行器)
IOThreadPoolExecutor
是 folly
库专门为 I/O 密集型任务 设计的线程池执行器。它在 ThreadPoolExecutor
的基础上进行了一些优化,更适合处理网络 I/O、磁盘 I/O 等待时间较长的任务。
IOThreadPoolExecutor
的核心特点是使用了 work-stealing 调度器 (work-stealing scheduler)。在传统的线程池中,任务通常会被放入一个全局的任务队列,线程从队列中取出任务执行。当某个线程空闲时,它只能从全局队列中获取任务。而在 work-stealing 调度器中,每个线程都有自己的本地任务队列。当一个线程完成本地队列中的任务后,如果全局队列为空,它会尝试从其他线程的本地队列中 "窃取" 任务来执行。
Work-stealing 调度器的优势:
① 减少竞争 (Reduced Contention):每个线程优先处理本地队列中的任务,减少了对全局队列的竞争,提高了调度效率。
② 更好的负载均衡 (Better Load Balancing):当某些线程的任务较少时,可以通过 work-stealing 机制从繁忙的线程窃取任务,实现更好的负载均衡,充分利用所有线程的资源。
③ 更适合 I/O 密集型任务 (More Suitable for I/O-Bound Tasks):对于 I/O 密集型任务,线程经常会因为等待 I/O 操作完成而进入阻塞状态。Work-stealing 调度器可以更好地利用这些空闲时间,让其他线程窃取任务并执行,提高整体的吞吐量。
IOThreadPoolExecutor
与 ThreadPoolExecutor
的主要区别:
特性 | ThreadPoolExecutor | IOThreadPoolExecutor |
---|---|---|
调度器 | 全局任务队列 | Work-stealing 调度器 |
优化目标 | 通用任务 | I/O 密集型任务 |
适用场景 | CPU 密集型和 I/O 密集型 | I/O 密集型 |
性能特点 | 均衡 | 更适合 I/O 密集型 |
代码示例:
1
#include <folly/executors/IOThreadPoolExecutor.h>
2
#include <iostream>
3
#include <thread>
4
5
int main() {
6
// 创建一个大小为 4 的 IO 线程池
7
auto executor = folly::IOThreadPoolExecutor::newFixedThreadPool(4);
8
9
std::cout << "Main thread ID: " << std::this_thread::get_id() << std::endl;
10
11
for (int i = 0; i < 5; ++i) {
12
executor->schedule([i] {
13
std::cout << "Task " << i << " running on thread ID: " << std::this_thread::get_id() << std::endl;
14
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟 I/O 等待
15
});
16
}
17
18
executor->join();
19
std::cout << "All tasks completed." << std::endl;
20
21
return 0;
22
}
输出结果与 ThreadPoolExecutor
类似,但内部调度机制不同,IOThreadPoolExecutor
更适合处理 I/O 密集型任务。
适用场景:
⚝ 网络服务器 (Network Servers):处理大量的网络请求,例如 Web 服务器、RPC 服务等。
⚝ 数据库操作 (Database Operations):执行数据库查询、写入等 I/O 操作。
⚝ 文件 I/O 密集型应用 (File I/O-Intensive Applications):处理大量的文件读写操作。
⚝ 需要高并发 I/O 处理的场景 (Scenarios Requiring High-Concurrency I/O Processing):例如,高并发的缓存系统、消息队列等。
总结来说,IOThreadPoolExecutor
是 folly
库针对 I/O 密集型任务优化的线程池执行器。通过 work-stealing 调度器,它可以更好地利用线程资源,提高 I/O 密集型应用的并发性能和吞吐量。在处理网络 I/O、文件 I/O 等任务时,IOThreadPoolExecutor
通常比 ThreadPoolExecutor
更有效率。
9.3 via()
:指定 Future 的执行上下文 (via()
: Specifying Execution Context for Future)
Future
的 via()
方法允许我们显式地指定后续链式操作(例如 then()
, map()
, flatMap()
等)的执行上下文,即指定这些操作将在哪个 Executor
上执行。这为我们提供了更精细的线程控制能力。
via()
方法接受一个 Executor
对象作为参数,并返回一个新的 Future
对象。后续的链式操作将会在指定的 Executor
上执行。
1
#include <folly/futures/Future.h>
2
#include <folly/executors/ThreadPoolExecutor.h>
3
#include <folly/executors/InlineExecutor.h>
4
#include <iostream>
5
#include <thread>
6
7
folly::Future<int> asyncTask() {
8
return folly::makeFuture(42);
9
}
10
11
int main() {
12
auto threadPoolExecutor = folly::ThreadPoolExecutor::newFixedThreadPool(2);
13
folly::InlineExecutor inlineExecutor;
14
15
std::cout << "Main thread ID: " << std::this_thread::get_id() << std::endl;
16
17
asyncTask()
18
.thenValue([](int value) {
19
std::cout << "First thenValue on thread ID: " << std::this_thread::get_id() << ", value: " << value << std::endl;
20
return value * 2;
21
})
22
.via(threadPoolExecutor.get()) // 指定后续操作在 threadPoolExecutor 上执行
23
.thenValue([](int value) {
24
std::cout << "Second thenValue on thread ID: " << std::this_thread::get_id() << ", value: " << value << std::endl;
25
return value + 10;
26
})
27
.via(&inlineExecutor) // 指定后续操作在 inlineExecutor 上执行
28
.thenValue([](int value) {
29
std::cout << "Third thenValue on thread ID: " << std::this_thread::get_id() << ", value: " << value << std::endl;
30
return value;
31
})
32
.get(); // 同步等待最终结果
33
34
threadPoolExecutor->join();
35
36
return 0;
37
}
可能的输出结果 (线程 ID 可能每次运行都不同):
1
Main thread ID: 140735718993792
2
First thenValue on thread ID: 140735718993792, value: 42
3
Second thenValue on thread ID: 140735718989568, value: 84
4
Third thenValue on thread ID: 140735718993792, value: 94
从输出结果可以看出:
① 第一个 thenValue
回调函数是在主线程 (Main thread ID: 140735718993792) 上执行的,因为 asyncTask()
返回的 Future
默认情况下会在调用 thenValue
的线程上执行回调。
② 第二个 thenValue
回调函数是在线程池的线程 (Thread ID: 140735718989568) 上执行的,因为在 thenValue
之前调用了 .via(threadPoolExecutor.get())
,指定了后续操作在 threadPoolExecutor
上执行。
③ 第三个 thenValue
回调函数又回到了主线程 (Main thread ID: 140735718993792) 上执行,因为在第二个 thenValue
之后调用了 .via(&inlineExecutor)
,指定了后续操作在 inlineExecutor
上执行,而 inlineExecutor
会在当前线程内联执行任务。
via()
方法的作用和优势:
① 精细的线程控制 (Fine-grained Thread Control):via()
允许开发者在 Future
链式操作的任意位置切换执行上下文,实现对线程执行的精细控制。
② 优化性能 (Performance Optimization):可以根据不同任务的特性,将任务分配到合适的 Executor
上执行,例如将 CPU 密集型任务放到 ThreadPoolExecutor
上,将 I/O 密集型任务放到 IOThreadPoolExecutor
上,或者将对延迟敏感的任务放到 InlineExecutor
上,从而优化性能。
③ 避免线程饥饿 (Avoiding Thread Starvation):在复杂的异步操作链中,如果所有操作都在同一个线程池中执行,可能会导致线程饥饿。使用 via()
可以将某些操作切换到不同的 Executor
上执行,避免线程饥饿问题。
④ 代码可读性和可维护性 (Code Readability and Maintainability):通过 via()
显式地指定执行上下文,可以提高代码的可读性和可维护性,使代码逻辑更加清晰。
适用场景:
⚝ 混合 CPU 密集型和 I/O 密集型任务 (Mixed CPU-Bound and I/O-Bound Tasks):在同一个异步操作链中,可能包含 CPU 密集型和 I/O 密集型任务。可以使用 via()
将不同类型的任务分配到不同的 Executor
上执行,例如 CPU 密集型任务使用 ThreadPoolExecutor
,I/O 密集型任务使用 IOThreadPoolExecutor
。
⚝ 需要在特定线程上执行的任务 (Tasks Requiring Execution on Specific Threads):例如,某些操作必须在 UI 线程或特定的 I/O 线程上执行。可以使用 via()
将这些操作切换到指定的线程上执行。
⚝ 性能优化 (Performance Optimization):通过分析异步操作链的性能瓶颈,可以使用 via()
将瓶颈操作切换到更合适的 Executor
上执行,从而优化性能。
总结来说,Future
的 via()
方法是一个强大的工具,它允许开发者精细地控制异步操作的执行上下文,实现更灵活、更高效的线程管理。合理使用 via()
可以优化性能、提高资源利用率、并增强代码的可读性和可维护性。
END_OF_CHAPTER
10. chapter 10: Future 的高级应用 (Advanced Applications of Future)
本章深入探讨 folly::Future
在高级场景下的应用,旨在帮助读者超越基本用法,掌握利用 Future
构建复杂异步系统的技巧。我们将涵盖使用 Future
构建异步数据流、实现并发控制、在微服务架构中的应用,以及 Future
与协程的整合等主题。通过学习本章内容,读者将能够更有效地利用 folly::Future
解决实际问题,提升异步编程能力。
10.1 使用 Future 构建异步数据流 (Building Asynchronous Data Streams with Future)
在传统的同步编程中,数据流通常通过迭代器或循环顺序处理。然而,在异步环境中,数据可能以非线性的方式到达,并且处理过程也可能是异步的。folly::Future
提供了一种强大的机制来构建和处理异步数据流,使得我们能够以声明式的方式处理数据,而无需显式地管理复杂的异步状态。
构建异步数据流的核心思想是将数据流的每个元素或一批元素的处理过程封装成一个 Future
。然后,通过 Future
的链式操作和组合操作,我们可以构建出复杂的数据处理管道(Data Processing Pipeline)。
示例:异步数据流处理
假设我们需要从多个数据源异步地获取数据,并对每个数据源的数据进行处理,最后将所有处理结果汇总。我们可以使用 Future
来构建这样的异步数据流。
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <vector>
4
#include <iostream>
5
6
using namespace folly;
7
8
// 模拟异步数据源,返回 Future<int>
9
Future<int> fetchDataFromSource(int sourceId) {
10
// 模拟耗时操作
11
return makeFuture(sourceId * 10).delayed(std::chrono::milliseconds(100));
12
}
13
14
// 处理单个数据项,返回 Future<int>
15
Future<int> processDataItem(int data) {
16
// 模拟数据处理
17
return makeFuture(data + 5).delayed(std::chrono::milliseconds(50));
18
}
19
20
int main() {
21
std::vector<int> sourceIds = {1, 2, 3, 4, 5};
22
std::vector<Future<int>> dataFutures;
23
24
// 为每个数据源创建获取数据的 Future
25
for (int sourceId : sourceIds) {
26
dataFutures.push_back(fetchDataFromSource(sourceId));
27
}
28
29
// 使用 collect() 等待所有数据获取完成
30
collect(dataFutures)
31
.thenValue([](std::vector<Try<int>> results) {
32
std::vector<Future<int>> processedFutures;
33
for (const auto& resultTry : results) {
34
if (resultTry.hasValue()) {
35
// 对每个获取到的数据进行处理
36
processedFutures.push_back(processDataItem(resultTry.value()));
37
} else {
38
// 处理数据获取异常
39
std::cerr << "Error fetching data: " << resultTry.exception().what() << std::endl;
40
}
41
}
42
return collect(processedFutures); // 再次 collect() 等待所有数据处理完成
43
})
44
.thenValue([](std::vector<Try<int>> processedResults) {
45
int totalSum = 0;
46
for (const auto& processedResultTry : processedResults) {
47
if (processedResultTry.hasValue()) {
48
totalSum += processedResultTry.value();
49
std::cout << "Processed data: " << processedResultTry.value() << std::endl;
50
} else {
51
// 处理数据处理异常
52
std::cerr << "Error processing data: " << processedResultTry.exception().what() << std::endl;
53
}
54
}
55
std::cout << "Total sum of processed data: " << totalSum << std::endl;
56
})
57
.get(); // 同步等待整个异步数据流处理完成
58
59
return 0;
60
}
代码解析:
① fetchDataFromSource(int sourceId)
函数模拟从异步数据源获取数据,并返回 Future<int>
。
② processDataItem(int data)
函数模拟对单个数据项进行异步处理,并返回 Future<int>
。
③ 在 main()
函数中,我们首先创建一组数据源 ID。
④ 然后,我们遍历数据源 ID,为每个数据源调用 fetchDataFromSource()
创建 Future<int>
,并将这些 Future
存储在 dataFutures
向量中。
⑤ collect(dataFutures)
用于等待所有数据获取操作完成,返回一个 Future<std::vector<Try<int>>>
,其中 Try<int>
封装了每个 Future
的结果(可能是值或异常)。
⑥ 在第一个 thenValue()
回调中,我们遍历数据获取结果,如果成功获取到数据,则调用 processDataItem()
对数据进行处理,并将处理结果的 Future
存储在 processedFutures
向量中。
⑦ 再次使用 collect(processedFutures)
等待所有数据处理操作完成。
⑧ 在第二个 thenValue()
回调中,我们遍历数据处理结果,计算总和并输出。
⑨ 最后,使用 get()
同步等待整个异步数据流处理完成。
关键点:
⚝ 异步数据源抽象:Future
可以很好地抽象异步数据源,使得我们可以以统一的方式处理来自不同来源的数据,而无需关心数据来源的具体实现细节。
⚝ 链式处理:通过 thenValue()
等链式操作,我们可以构建数据处理管道,将数据从一个处理阶段传递到下一个阶段,实现复杂的数据处理逻辑。
⚝ 错误处理:Try<T>
类型可以有效地封装异步操作的结果,包括成功的值和异常,方便进行统一的错误处理。
⚝ 并发性:collect()
等组合操作可以并发地执行多个异步操作,提高数据流处理的效率。
通过 Future
构建异步数据流,可以有效地处理来自多个异步源的数据,并进行复杂的异步数据处理,提高系统的响应性和吞吐量。
10.2 使用 Future 实现并发控制 (Implementing Concurrency Control with Future)
并发控制是多线程和异步编程中至关重要的一个方面。folly::Future
不仅可以用于异步操作的编排,还可以作为实现各种并发控制机制的基础。例如,我们可以使用 Future
和 Promise
来实现信号量(Semaphore)、互斥锁(Mutex)、条件变量(Condition Variable)等并发原语。
信号量 (Semaphore)
信号量是一种用于控制对共享资源访问的计数器。它可以限制同时访问资源的线程数量。我们可以使用 Future
和 Promise
来实现一个简单的二元信号量(Binary Semaphore),即计数器只能取 0 或 1 的信号量。
1
#include <folly/Future.h>
2
#include <folly/Promise.h>
3
#include <folly/executors/InlineExecutor.h>
4
#include <iostream>
5
6
using namespace folly;
7
8
class BinarySemaphore {
9
public:
10
BinarySemaphore() : available_(true) {}
11
12
Future<void> acquire() {
13
if (available_) {
14
available_ = false;
15
return makeFuture(); // 立即返回已完成的 Future
16
} else {
17
// 如果资源不可用,则创建一个 Promise,等待资源释放
18
Promise<void> p;
19
waitQueue_.push_back(std::move(p));
20
return p.getFuture();
21
}
22
}
23
24
void release() {
25
if (!waitQueue_.empty()) {
26
// 如果有等待的 Future,则 fulfill 第一个等待的 Promise
27
auto p = std::move(waitQueue_.front());
28
waitQueue_.pop_front();
29
p.setValue();
30
} else {
31
available_ = true; // 否则,释放资源
32
}
33
}
34
35
private:
36
bool available_;
37
std::deque<Promise<void>> waitQueue_; // 等待队列
38
};
39
40
Future<void> accessResource(BinarySemaphore& semaphore, int taskId) {
41
return semaphore.acquire()
42
.thenValue([&semaphore, taskId](Unit) {
43
std::cout << "Task " << taskId << " acquired semaphore and is accessing resource." << std::endl;
44
// 模拟访问共享资源
45
return makeFuture().delayed(std::chrono::milliseconds(200));
46
})
47
.thenValue([&semaphore, taskId](Unit) {
48
std::cout << "Task " << taskId << " finished accessing resource and releasing semaphore." << std::endl;
49
semaphore.release();
50
});
51
}
52
53
int main() {
54
BinarySemaphore semaphore;
55
std::vector<Future<void>> taskFutures;
56
57
for (int i = 1; i <= 3; ++i) {
58
taskFutures.push_back(accessResource(semaphore, i));
59
}
60
61
collectAll(taskFutures).get(); // 等待所有任务完成
62
63
return 0;
64
}
代码解析:
① BinarySemaphore
类使用 available_
变量记录资源是否可用,waitQueue_
队列存储等待资源的 Promise
。
② acquire()
方法尝试获取信号量。如果资源可用,则立即返回已完成的 Future
并将 available_
设置为 false
。如果资源不可用,则创建一个新的 Promise
,将其添加到 waitQueue_
,并返回与该 Promise
关联的 Future
。
③ release()
方法释放信号量。如果 waitQueue_
不为空,则从队列中取出一个 Promise
并调用 setValue()
fulfill 它,从而唤醒等待的 Future
。否则,将 available_
设置为 true
,表示资源可用。
④ accessResource()
函数模拟一个需要访问共享资源的任务。它首先调用 semaphore.acquire()
获取信号量,然后模拟访问资源的操作,最后调用 semaphore.release()
释放信号量。
⑤ 在 main()
函数中,我们创建了一个 BinarySemaphore
对象和多个任务 Future
,并使用 collectAll()
等待所有任务完成。
关键点:
⚝ Promise 的等待队列:waitQueue_
队列用于存储等待资源的 Promise
,当资源释放时,可以按照 FIFO (First-In, First-Out) 的顺序唤醒等待的任务。
⚝ Future 的异步等待:acquire()
方法返回的 Future
允许任务异步地等待信号量,避免线程阻塞。
⚝ 资源管理:BinarySemaphore
类封装了信号量的获取和释放逻辑,确保对共享资源的互斥访问。
除了信号量,我们还可以使用类似的 Future
和 Promise
机制来实现更复杂的并发控制原语,例如互斥锁、读写锁、条件变量等,从而构建更健壮和高效的并发系统。
10.3 Future 在微服务架构中的应用 (Application of Future in Microservice Architecture)
微服务架构强调将应用程序拆分成一组小型、自治的服务,这些服务通过网络进行通信。在微服务架构中,服务之间的通信通常是异步的,以提高系统的响应性和可伸缩性。folly::Future
在微服务架构中扮演着重要的角色,可以用于处理服务间的异步通信、请求编排、错误处理和熔断降级等。
服务间异步通信
在微服务架构中,服务之间的通信通常使用 RPC (Remote Procedure Call) 或消息队列等异步通信机制。folly::Future
可以很好地与这些异步通信机制集成,使得服务调用可以以非阻塞的方式进行。
例如,假设服务 A 需要调用服务 B 和服务 C 获取数据,并将两个服务返回的数据进行聚合。使用 Future
,我们可以并发地调用服务 B 和服务 C,然后使用 collect()
等待两个服务都返回结果,最后进行数据聚合。
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
5
using namespace folly;
6
7
// 模拟异步 RPC 调用服务 B,返回 Future<std::string>
8
Future<std::string> callServiceB() {
9
std::cout << "Calling Service B..." << std::endl;
10
return makeFuture(std::string("Data from Service B")).delayed(std::chrono::milliseconds(150));
11
}
12
13
// 模拟异步 RPC 调用服务 C,返回 Future<std::string>
14
Future<std::string> callServiceC() {
15
std::cout << "Calling Service C..." << std::endl;
16
return makeFuture(std::string("Data from Service C")).delayed(std::chrono::milliseconds(100));
17
}
18
19
Future<std::string> aggregateData() {
20
return collect(callServiceB(), callServiceC())
21
.thenValue([](std::tuple<Try<std::string>, Try<std::string>> results) {
22
std::string dataB, dataC;
23
if (std::get<0>(results).hasValue()) {
24
dataB = std::get<0>(results).value();
25
} else {
26
dataB = "Error from Service B";
27
}
28
if (std::get<1>(results).hasValue()) {
29
dataC = std::get<1>(results).value();
30
} else {
31
dataC = "Error from Service C";
32
}
33
return makeFuture(dataB + " and " + dataC);
34
});
35
}
36
37
int main() {
38
aggregateData()
39
.thenValue([](std::string aggregatedData) {
40
std::cout << "Aggregated data: " << aggregatedData << std::endl;
41
})
42
.get();
43
44
return 0;
45
}
代码解析:
① callServiceB()
和 callServiceC()
函数模拟异步 RPC 调用服务 B 和服务 C,并返回 Future<std::string>
。
② aggregateData()
函数使用 collect(callServiceB(), callServiceC())
并发地调用服务 B 和服务 C,并等待两个服务都返回结果。
③ 在 thenValue()
回调中,我们从 collect()
返回的结果中获取服务 B 和服务 C 的数据,并将它们聚合在一起。
④ main()
函数调用 aggregateData()
获取聚合数据并输出。
请求编排 (Request Orchestration)
在复杂的微服务场景中,一个用户请求可能需要调用多个服务才能完成。Future
的链式操作和组合操作可以用于编排这些服务调用,构建复杂的请求处理流程。例如,可以使用 then()
顺序调用服务,使用 collect()
并发调用服务,使用 select()
选择最先返回的服务等。
错误处理和熔断降级 (Error Handling and Circuit Breaker)
在微服务架构中,服务之间的依赖关系复杂,任何一个服务的故障都可能导致整个调用链的失败。Future
的异常处理机制可以用于处理服务调用中的错误,并实现熔断降级等容错策略。例如,可以使用 catch()
捕获服务调用异常,使用 recover()
或 recoverWith()
从异常中恢复,或者使用熔断器模式(Circuit Breaker Pattern)防止服务雪崩。
关键点:
⚝ 异步通信集成:Future
可以与各种异步通信机制(RPC, 消息队列)集成,实现非阻塞的服务调用。
⚝ 请求编排能力:Future
的链式和组合操作可以用于编排复杂的服务调用流程。
⚝ 容错机制:Future
的异常处理机制可以用于实现微服务架构中的错误处理和容错策略。
folly::Future
为构建高可用、高可伸缩的微服务架构提供了强大的异步编程基础。
10.4 Future 与协程 (Future and Coroutines)
协程(Coroutines)是一种轻量级的并发编程模型,它允许程序在执行过程中挂起和恢复,从而实现非阻塞的异步操作。C++20 引入了标准协程,folly::Future
可以与协程很好地结合使用,提供更简洁和易于理解的异步编程方式。
Future 转换为协程
我们可以使用 co_await
关键字等待一个 Future
完成,并将 Future
的结果作为协程的返回值。这使得我们可以在协程中以同步的方式编写异步代码,而无需显式地使用 then()
等回调函数。
1
#include <folly/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
#include <coroutine>
5
6
using namespace folly;
7
8
// 模拟异步操作,返回 Future<int>
9
Future<int> asyncOperation(int value) {
10
return makeFuture(value * 2).delayed(std::chrono::milliseconds(100));
11
}
12
13
// 使用协程等待 Future
14
Task<int> coroutineExample() {
15
int result1 = co_await asyncOperation(5);
16
std::cout << "Result 1: " << result1 << std::endl;
17
int result2 = co_await asyncOperation(result1);
18
std::cout << "Result 2: " << result2 << std::endl;
19
co_return result2;
20
}
21
22
int main() {
23
coroutineExample().get(); // 启动协程并同步等待结果
24
return 0;
25
}
代码解析:
① asyncOperation(int value)
函数模拟一个异步操作,返回 Future<int>
。
② coroutineExample()
函数是一个协程,使用 Task<int>
作为返回类型。Task
是一个简化的协程返回类型,类似于 Future
,用于表示异步操作的结果。
③ 在协程中,我们使用 co_await asyncOperation(5)
等待 asyncOperation(5)
返回的 Future
完成,并将 Future
的结果赋值给 result1
。
④ 协程的执行流程类似于同步代码,但实际上 co_await
会挂起协程的执行,直到 Future
完成,从而实现非阻塞的异步操作。
⑤ main()
函数调用 coroutineExample().get()
启动协程并同步等待协程的返回值。
协程生成 Future
我们也可以在协程中创建 Promise
,并返回与 Promise
关联的 Future
。这使得我们可以将协程作为异步任务的生产者,将协程内部的异步操作结果传递给 Future
。
1
#include <folly/Future.h>
2
#include <folly/Promise.h>
3
#include <folly/executors/InlineExecutor.h>
4
#include <iostream>
5
#include <coroutine>
6
7
using namespace folly;
8
9
// 协程生成 Future
10
Future<int> coroutineToFuture() {
11
Promise<int> promise;
12
auto future = promise.getFuture();
13
14
// 在协程中异步设置 Promise 的值
15
[&promise]() -> Task<void> {
16
co_await std::suspend_never{}; // 确保在异步上下文中执行
17
promise.setValue(42);
18
co_return;
19
}(); // 立即启动协程
20
21
return future;
22
}
23
24
int main() {
25
coroutineToFuture()
26
.thenValue([](int result) {
27
std::cout << "Result from coroutine: " << result << std::endl;
28
})
29
.get();
30
31
return 0;
32
}
代码解析:
① coroutineToFuture()
函数创建一个 Promise<int>
和与之关联的 Future<int>
。
② 使用 lambda 表达式定义一个立即执行的协程 [&promise]() -> Task<void> { ... }()
。
③ 在协程中,co_await std::suspend_never{}
确保协程在异步上下文中执行(尽管在这个例子中并不是严格必需的,但作为最佳实践)。
④ promise.setValue(42)
在协程中异步地设置 Promise
的值,从而完成与 Promise
关联的 Future
。
⑤ coroutineToFuture()
函数返回 future
。
⑥ main()
函数调用 coroutineToFuture()
获取 Future
,并使用 thenValue()
处理 Future
的结果。
关键点:
⚝ co_await
等待 Future:co_await
关键字使得在协程中等待 Future
变得非常简洁,提高了异步代码的可读性。
⚝ 协程与 Future 的互操作性:Future
和协程可以互相转换,使得我们可以灵活地选择合适的异步编程模型。
⚝ 简化异步编程:协程可以隐藏异步编程的复杂性,使得异步代码更接近同步代码的风格,降低了异步编程的门槛。
folly::Future
与协程的结合,为 C++ 异步编程提供了更强大和更易用的工具,可以显著提高异步代码的开发效率和可维护性。
总结
本章深入探讨了 folly::Future
的高级应用,包括构建异步数据流、实现并发控制、在微服务架构中的应用以及与协程的整合。通过学习这些高级应用,读者可以更全面地理解 folly::Future
的强大功能,并将其应用于更复杂的异步编程场景中。掌握这些高级技巧将有助于读者构建更高效、更健壮的异步系统。
END_OF_CHAPTER
11. chapter 11: 实战案例分析 (Practical Case Studies)
11.1 案例一:异步文件 I/O 操作 (Case Study 1: Asynchronous File I/O Operations)
在现代应用程序开发中,文件 I/O 操作是不可或缺的一部分。无论是读取配置文件、处理日志文件,还是加载大型数据集,文件 I/O 都扮演着关键角色。然而,传统的文件 I/O 操作通常是同步阻塞(Synchronous Blocking)的,这意味着当程序发起一个文件读取或写入请求时,它必须等待操作完成才能继续执行后续任务。在高并发和高性能要求的场景下,同步阻塞的文件 I/O 容易成为性能瓶颈,导致程序响应延迟,资源利用率低下。
异步文件 I/O(Asynchronous File I/O) 提供了一种更高效的解决方案。它允许程序发起文件 I/O 请求后立即返回,无需等待操作完成。当 I/O 操作完成时,系统会通知程序,程序再进行后续处理。这种非阻塞的方式极大地提高了程序的并发性和响应速度,尤其是在处理大量并发 I/O 请求时优势更加明显。
folly::Future
和 folly::Promise
提供了一种优雅的方式来实现异步文件 I/O 操作。下面,我们通过一个简单的案例来演示如何使用 folly::Future
和 folly::Promise
实现异步文件读取。
案例描述:
假设我们需要编写一个程序,异步读取一个文本文件的内容,并在读取完成后打印到控制台。
代码示例:
1
#include <folly/Future.h>
2
#include <folly/Promise.h>
3
#include <folly/Executor.h>
4
#include <folly/executors/IOThreadPoolExecutor.h>
5
#include <folly/io/async/EventBaseManager.h>
6
#include <folly/io/async/EventBase.h>
7
8
#include <fstream>
9
#include <iostream>
10
#include <string>
11
#include <stdexcept>
12
13
using namespace folly;
14
15
Future<std::string> asyncReadFile(const std::string& filename, Executor* executor) {
16
Promise<std::string> promise;
17
Future<std::string> future = promise.getFuture();
18
19
executor->add([filename, promise = std::move(promise)]() mutable {
20
std::ifstream file(filename);
21
if (!file.is_open()) {
22
promise.setException(std::runtime_error("Failed to open file: " + filename));
23
return;
24
}
25
26
std::string content;
27
std::string line;
28
while (std::getline(file, line)) {
29
content += line + "\n";
30
}
31
file.close();
32
promise.setValue(content);
33
});
34
35
return future;
36
}
37
38
int main() {
39
// 创建 IO 线程池执行器,用于执行文件 I/O 操作
40
IOThreadPoolExecutor executor(4);
41
// 获取 EventBase
42
EventBase* evb = EventBaseManager::get()->getEventBase();
43
44
std::string filename = "example.txt";
45
46
// 异步读取文件内容
47
Future<std::string> fileContentFuture = asyncReadFile(filename, &executor);
48
49
// 使用 then 方法异步处理文件读取结果
50
fileContentFuture.thenValue([](const std::string& content) {
51
std::cout << "File content:\n" << content << std::endl;
52
}).thenError([](const std::exception& e) {
53
std::cerr << "Error reading file: " << e.what() << std::endl;
54
});
55
56
// 运行 EventBase,等待异步操作完成
57
evb->loop();
58
59
return 0;
60
}
代码解析:
① asyncReadFile
函数:
▮▮▮▮⚝ 接收文件名 filename
和执行器 executor
作为参数。
▮▮▮▮⚝ 创建一个 Promise<std::string>
对象 promise
,用于设置异步操作的结果。
▮▮▮▮⚝ 通过 promise.getFuture()
获取与 promise
关联的 Future<std::string>
对象 future
,该 future
将代表异步文件读取操作的结果。
▮▮▮▮⚝ 使用 executor->add()
将一个 lambda 表达式 提交到执行器中异步执行。
▮▮▮▮⚝ 在 lambda 表达式中:
▮▮▮▮⚝ 打开指定的文件 filename
。
▮▮▮▮⚝ 如果文件打开失败,使用 promise.setException()
设置 future
的异常状态,并返回。
▮▮▮▮⚝ 循环读取文件内容,并将内容累加到 content
字符串中。
▮▮▮▮⚝ 文件读取完成后,使用 promise.setValue()
将文件内容设置为 future
的值,表示异步操作成功完成。
▮▮▮▮⚝ 返回 future
对象。
② main
函数:
▮▮▮▮⚝ 创建一个 IOThreadPoolExecutor
对象 executor
,用于执行文件 I/O 操作。IOThreadPoolExecutor
专门为 I/O 密集型任务设计,能够高效地处理异步 I/O 操作。
▮▮▮▮⚝ 获取 EventBase
对象 evb
。EventBase
是 folly
异步编程的核心,负责事件循环和 I/O 事件的管理。
▮▮▮▮⚝ 指定要读取的文件名 filename
为 "example.txt"。
▮▮▮▮⚝ 调用 asyncReadFile
函数异步读取文件内容,并将返回的 Future<std::string>
对象赋值给 fileContentFuture
。
▮▮▮▮⚝ 使用 thenValue()
方法注册一个 回调函数,当 fileContentFuture
成功完成(即文件读取成功)时,该回调函数会被调用,打印文件内容到控制台。
▮▮▮▮⚝ 使用 thenError()
方法注册一个 错误处理回调函数,当 fileContentFuture
失败(即文件读取过程中发生异常)时,该回调函数会被调用,打印错误信息到控制台。
▮▮▮▮⚝ 调用 evb->loop()
启动 EventBase
的事件循环。EventBase
会监听 I/O 事件,并在异步操作完成时触发相应的回调函数。loop()
函数会阻塞当前线程,直到 EventBase
停止循环(在本例中,异步文件读取操作完成后,程序会自动退出循环)。
编译和运行:
- 创建
example.txt
文件:在与代码相同的目录下创建一个名为example.txt
的文本文件,并写入一些内容。 - 编译代码:使用支持 C++17 或更高版本的编译器编译上述代码,并链接
folly
库。编译命令示例(假设已正确安装folly
):
1
g++ -std=c++17 async_file_io.cpp -o async_file_io -lfolly -lglog -pthread
- 运行程序:
1
./async_file_io
1
程序运行后,如果文件读取成功,将在控制台输出 `example.txt` 文件的内容;如果文件读取失败(例如文件不存在或无法打开),将在控制台输出错误信息。
优势与应用场景:
⚝ 提高并发性:异步文件 I/O 允许程序在等待文件 I/O 操作完成的同时继续执行其他任务,从而提高了程序的并发性。
⚝ 提升响应速度:对于需要处理大量文件 I/O 操作的应用程序,异步 I/O 可以显著降低响应延迟,提升用户体验。
⚝ 资源利用率:异步 I/O 可以更有效地利用系统资源,避免线程阻塞等待 I/O 操作,从而提高资源利用率。
适用场景:
⚝ 日志处理:异步写入日志文件,避免日志 I/O 阻塞主线程。
⚝ 数据备份与恢复:异步执行数据备份和恢复操作,提高效率。
⚝ 文件服务器:构建高性能文件服务器,处理大量并发文件访问请求。
⚝ 大数据处理:在数据处理管道中,异步读取和写入数据文件,加速数据处理流程。
总结:
本案例演示了如何使用 folly::Future
和 folly::Promise
实现简单的异步文件读取操作。通过使用异步 I/O 和 folly
提供的异步编程工具,我们可以构建更高效、更具响应性的应用程序,尤其是在处理文件 I/O 密集型任务时,异步 I/O 的优势将更加明显。在实际应用中,可以根据具体需求,结合 folly
库提供的其他异步工具和组件,构建更复杂、更强大的异步文件 I/O 系统。
11.2 案例二:异步网络请求处理 (Case Study 2: Asynchronous Network Request Handling)
网络请求是现代应用程序中另一个常见的 I/O 操作。与文件 I/O 类似,传统的同步网络请求(Synchronous Network Request)也会阻塞线程,导致程序在等待网络响应时无法执行其他任务。在高并发的网络应用场景下,同步网络请求容易成为性能瓶颈,影响程序的吞吐量和响应速度。
异步网络请求(Asynchronous Network Request) 允许程序发起网络请求后立即返回,无需等待服务器响应。当服务器响应到达时,程序会收到通知并处理响应数据。这种非阻塞的方式可以显著提高网络应用的并发处理能力和响应速度。
folly::Future
和 folly::Promise
同样可以用于实现异步网络请求处理。虽然 folly
库本身没有直接提供完整的 HTTP 客户端库,但它可以与其他的异步网络库(例如 libevent
、asio
等)结合使用,构建高效的异步网络应用。
为了简化示例,我们假设已经存在一个名为 AsyncHttpClient
的异步 HTTP 客户端库,该库提供了一个 asyncGet
方法,用于异步发起 GET 请求并返回 folly::Future<HttpResponse>
对象,其中 HttpResponse
表示 HTTP 响应。
案例描述:
假设我们需要编写一个程序,异步发起一个 HTTP GET 请求,获取指定 URL 的内容,并在请求成功后打印响应状态码和响应体内容。
代码示例:
1
#include <folly/Future.h>
2
#include <folly/Promise.h>
3
#include <folly/Executor.h>
4
#include <folly/executors/IOThreadPoolExecutor.h>
5
#include <folly/io/async/EventBaseManager.h>
6
#include <folly/io/async/EventBase.h>
7
8
#include <iostream>
9
#include <string>
10
#include <stdexcept>
11
12
using namespace folly;
13
14
// 假设的异步 HTTP 客户端库 (Simplified Asynchronous HTTP Client Library)
15
struct HttpResponse {
16
int statusCode;
17
std::string body;
18
};
19
20
class AsyncHttpClient {
21
public:
22
Future<HttpResponse> asyncGet(const std::string& url, Executor* executor) {
23
Promise<HttpResponse> promise;
24
Future<HttpResponse> future = promise.getFuture();
25
26
executor->add([url, promise = std::move(promise)]() mutable {
27
// 模拟异步网络请求 (Simulate asynchronous network request)
28
// 在实际应用中,这里会使用真正的异步网络库发起请求
29
// (In real applications, a real asynchronous network library would be used here)
30
std::cout << "发起异步网络请求到: " << url << std::endl;
31
// 模拟延迟 (Simulate delay)
32
std::this_thread::sleep_for(std::chrono::seconds(2));
33
34
// 模拟成功响应 (Simulate successful response)
35
HttpResponse response;
36
response.statusCode = 200;
37
response.body = "<html><body><h1>Hello, Async World!</h1></body></html>";
38
promise.setValue(response);
39
40
// 模拟异常响应 (Simulate exception response)
41
// promise.setException(std::runtime_error("Network request failed"));
42
});
43
44
return future;
45
}
46
};
47
48
49
int main() {
50
// 创建 IO 线程池执行器
51
IOThreadPoolExecutor executor(4);
52
// 获取 EventBase
53
EventBase* evb = EventBaseManager::get()->getEventBase();
54
// 创建异步 HTTP 客户端实例
55
AsyncHttpClient httpClient;
56
57
std::string url = "http://example.com";
58
59
// 异步发起 HTTP GET 请求
60
Future<HttpResponse> httpResponseFuture = httpClient.asyncGet(url, &executor);
61
62
// 使用 then 方法异步处理网络请求结果
63
httpResponseFuture.thenValue([](const HttpResponse& response) {
64
std::cout << "HTTP 状态码: " << response.statusCode << std::endl;
65
std::cout << "响应体内容:\n" << response.body << std::endl;
66
}).thenError([](const std::exception& e) {
67
std::cerr << "网络请求失败: " << e.what() << std::endl;
68
});
69
70
// 运行 EventBase,等待异步操作完成
71
evb->loop();
72
73
return 0;
74
}
代码解析:
① AsyncHttpClient
类(模拟):
▮▮▮▮⚝ 提供一个 asyncGet
方法,模拟异步发起 HTTP GET 请求。
▮▮▮▮⚝ 接收 URL url
和执行器 executor
作为参数。
▮▮▮▮⚝ 创建 Promise<HttpResponse>
和 Future<HttpResponse>
对象,用于处理异步操作的结果。
▮▮▮▮⚝ 使用 executor->add()
将一个 lambda 表达式提交到执行器中异步执行。
▮▮▮▮⚝ 在 lambda 表达式中:
▮▮▮▮⚝ 模拟发起网络请求的动作,打印请求 URL。
▮▮▮▮⚝ 模拟网络延迟,使用 std::this_thread::sleep_for
暂停 2 秒。
▮▮▮▮⚝ 模拟成功响应,创建一个 HttpResponse
对象,设置状态码为 200,响应体内容为 HTML 字符串,并使用 promise.setValue()
设置 future
的值。
▮▮▮▮⚝ (注释部分)模拟异常响应,可以使用 promise.setException()
设置 future
的异常状态。
▮▮▮▮⚝ 返回 future
对象。
② main
函数:
▮▮▮▮⚝ 创建 IOThreadPoolExecutor
和 EventBase
对象。
▮▮▮▮⚝ 创建 AsyncHttpClient
实例 httpClient
。
▮▮▮▮⚝ 指定请求 URL url
为 "http://example.com"。
▮▮▮▮⚝ 调用 httpClient.asyncGet
异步发起 HTTP GET 请求,并将返回的 Future<HttpResponse>
对象赋值给 httpResponseFuture
。
▮▮▮▮⚝ 使用 thenValue()
方法注册成功回调函数,处理 HTTP 响应,打印状态码和响应体内容。
▮▮▮▮⚝ 使用 thenError()
方法注册错误处理回调函数,处理网络请求失败的情况,打印错误信息。
▮▮▮▮⚝ 启动 EventBase
的事件循环 evb->loop()
。
编译和运行:
- 编译代码:使用支持 C++17 或更高版本的编译器编译上述代码,并链接
folly
库。编译命令示例:
1
g++ -std=c++17 async_http_request.cpp -o async_http_request -lfolly -lglog -pthread
- 运行程序:
1
./async_http_request
1
程序运行后,将模拟发起异步网络请求,并在 2 秒延迟后,如果模拟成功响应,将在控制台输出 HTTP 状态码和响应体内容;如果模拟异常响应(取消注释 `promise.setException`),将在控制台输出错误信息。
超时处理:
在实际的网络请求中,超时处理至关重要。folly::Future
提供了 within()
方法来设置 Future 的超时时间。我们可以使用 within()
方法为 httpResponseFuture
设置超时时间,例如 5 秒:
1
Future<HttpResponse> httpResponseFuture = httpClient.asyncGet(url, &executor)
2
.within(std::chrono::seconds(5));
如果网络请求在 5 秒内没有完成,httpResponseFuture
将会抛出 TimeoutException
异常。我们可以在 thenError()
回调函数中捕获 TimeoutException
并进行相应的处理。
1
httpResponseFuture.thenValue([](const HttpResponse& response) {
2
// ...
3
}).thenError([](const std::exception& e) {
4
if (dynamic_cast<const TimeoutException*>(&e)) {
5
std::cerr << "网络请求超时!" << std::endl;
6
} else {
7
std::cerr << "网络请求失败: " << e.what() << std::endl;
8
}
9
});
重试机制:
对于网络请求,重试机制也是常见的容错手段。我们可以使用 folly::Future
的链式操作和错误处理机制来实现简单的重试逻辑。例如,在 thenError()
回调函数中,如果捕获到网络请求失败的异常,可以延迟一段时间后重新发起请求。更复杂的重试策略可以使用 指数退避(Exponential Backoff) 等算法。
优势与应用场景:
⚝ 高并发处理能力:异步网络请求允许服务器同时处理大量并发连接,提高服务器的吞吐量和并发处理能力。
⚝ 低延迟响应:异步网络请求可以减少请求等待时间,提高应用程序的响应速度,改善用户体验。
⚝ 资源高效利用:异步网络请求避免线程阻塞等待网络 I/O,可以更有效地利用系统资源,降低资源消耗。
适用场景:
⚝ Web 服务器:构建高性能 Web 服务器,处理大量并发 HTTP 请求。
⚝ API 网关:实现异步 API 网关,转发和聚合后端服务的请求。
⚝ 微服务架构:在微服务架构中,服务之间的异步通信可以提高系统的整体性能和弹性。
⚝ 移动应用后端:构建高并发、低延迟的移动应用后端服务。
总结:
本案例演示了如何使用 folly::Future
和模拟的 AsyncHttpClient
库实现异步网络请求处理。通过使用异步网络请求和 folly
提供的异步编程工具,我们可以构建高性能、高并发的网络应用程序。在实际应用中,可以结合成熟的异步网络库(如 libevent
、asio
)和 folly::Future
,构建更强大、更可靠的异步网络服务。同时,需要关注超时处理、重试机制、错误处理等关键问题,提高网络应用的健壮性和稳定性。
11.3 案例三:构建高并发的缓存系统 (Case Study 3: Building a High-Concurrency Cache System)
缓存是提高应用程序性能的关键技术之一。通过将热点数据存储在高速缓存中,可以减少对后端存储系统的访问,从而降低延迟、提高吞吐量。在高并发场景下,缓存系统的性能至关重要。同步阻塞的缓存操作容易成为性能瓶颈,而异步缓存(Asynchronous Cache) 可以提供更高的并发性和更低的延迟。
folly::Future
非常适合构建异步缓存系统。我们可以使用 folly::Future
来表示缓存操作的结果,并利用 folly::Future
的链式操作和组合操作来实现复杂的缓存逻辑,例如缓存穿透、缓存击穿、缓存雪崩的应对策略。
案例描述:
假设我们需要构建一个简单的异步缓存系统,用于缓存键值对数据。缓存系统需要提供 asyncGet
和 asyncSet
两个异步方法,分别用于异步获取和设置缓存数据。
代码示例:
1
#include <folly/Future.h>
2
#include <folly/Promise.h>
3
#include <folly/Executor.h>
4
#include <folly/executors/IOThreadPoolExecutor.h>
5
#include <folly/io/async/EventBaseManager.h>
6
#include <folly/io/async/EventBase.h>
7
#include <folly/concurrency/ConcurrentHashMap.h>
8
9
#include <iostream>
10
#include <string>
11
#include <memory>
12
#include <stdexcept>
13
14
using namespace folly;
15
16
// 异步缓存类 (Asynchronous Cache Class)
17
class AsyncCache {
18
private:
19
ConcurrentHashMap<std::string, std::string> cache_;
20
Executor* executor_;
21
22
public:
23
AsyncCache(Executor* executor) : executor_(executor) {}
24
25
Future<std::string> asyncGet(const std::string& key) {
26
Promise<std::string> promise;
27
Future<std::string> future = promise.getFuture();
28
29
executor_->add([this, key, promise = std::move(promise)]() mutable {
30
// 模拟缓存查询延迟 (Simulate cache lookup delay)
31
std::this_thread::sleep_for(std::chrono::milliseconds(50));
32
33
auto it = cache_.find(key);
34
if (it != cache_.end()) {
35
// 缓存命中 (Cache hit)
36
promise.setValue(it->second);
37
} else {
38
// 缓存未命中 (Cache miss)
39
promise.setException(std::runtime_error("Cache miss for key: " + key));
40
}
41
});
42
43
return future;
44
}
45
46
Future<void> asyncSet(const std::string& key, const std::string& value) {
47
Promise<void> promise;
48
Future<void> future = promise.getFuture();
49
50
executor_->add([this, key, value, promise = std::move(promise)]() mutable {
51
// 模拟缓存写入延迟 (Simulate cache write delay)
52
std::this_thread::sleep_for(std::chrono::milliseconds(20));
53
54
cache_.insert_or_assign(key, value);
55
promise.setValue();
56
});
57
58
return future;
59
}
60
};
61
62
63
int main() {
64
// 创建 IO 线程池执行器
65
IOThreadPoolExecutor executor(4);
66
// 获取 EventBase
67
EventBase* evb = EventBaseManager::get()->getEventBase();
68
// 创建异步缓存实例
69
AsyncCache cache(&executor);
70
71
std::string key = "mykey";
72
std::string value = "myvalue";
73
74
// 异步设置缓存
75
Future<void> setFuture = cache.asyncSet(key, value);
76
77
// 异步获取缓存
78
Future<std::string> getFuture = setFuture.thenValue([&cache, key](Unit) {
79
return cache.asyncGet(key);
80
});
81
82
// 处理缓存获取结果
83
getFuture.thenValue([](const std::string& cachedValue) {
84
std::cout << "缓存获取成功,Value: " << cachedValue << std::endl;
85
}).thenError([](const std::exception& e) {
86
std::cerr << "缓存获取失败: " << e.what() << std::endl;
87
});
88
89
// 异步获取不存在的 key
90
Future<std::string> missFuture = cache.asyncGet("non_existent_key");
91
missFuture.thenValue([](const std::string& cachedValue) {
92
std::cout << "缓存获取成功 (意外),Value: " << cachedValue << std::endl;
93
}).thenError([](const std::exception& e) {
94
std::cerr << "缓存获取失败 (预期): " << e.what() << std::endl;
95
});
96
97
98
// 运行 EventBase,等待异步操作完成
99
evb->loop();
100
101
return 0;
102
}
代码解析:
① AsyncCache
类:
▮▮▮▮⚝ 使用 folly::ConcurrentHashMap
作为缓存的底层存储结构。ConcurrentHashMap
是一个高效的并发哈希表,适用于高并发读写场景。
▮▮▮▮⚝ 构造函数接收一个 Executor
指针 executor_
,用于执行异步缓存操作。
▮▮▮▮⚝ asyncGet
方法:
▮▮▮▮⚝ 接收缓存键 key
作为参数。
▮▮▮▮⚝ 创建 Promise<std::string>
和 Future<std::string>
对象。
▮▮▮▮⚝ 使用 executor_->add()
将一个 lambda 表达式提交到执行器中异步执行。
▮▮▮▮⚝ 在 lambda 表达式中:
▮▮▮▮▮▮▮▮⚝ 模拟缓存查询延迟,使用 std::this_thread::sleep_for
暂停 50 毫秒。
▮▮▮▮▮▮▮▮⚝ 使用 cache_.find(key)
在 ConcurrentHashMap
中查找键 key
。
▮▮▮▮▮▮▮▮⚝ 如果缓存命中(找到键),使用 promise.setValue()
将缓存值设置为 future
的值。
▮▮▮▮▮▮▮▮⚝ 如果缓存未命中(未找到键),使用 promise.setException()
设置 future
的异常状态,抛出 std::runtime_error
异常。
▮▮▮▮⚝ 返回 future
对象。
▮▮▮▮⚝ asyncSet
方法:
▮▮▮▮⚝ 接收缓存键 key
和值 value
作为参数。
▮▮▮▮⚝ 创建 Promise<void>
和 Future<void>
对象。
▮▮▮▮⚝ 使用 executor_->add()
将一个 lambda 表达式提交到执行器中异步执行。
▮▮▮▮⚝ 在 lambda 表达式中:
▮▮▮▮▮▮▮▮⚝ 模拟缓存写入延迟,使用 std::this_thread::sleep_for
暂停 20 毫秒。
▮▮▮▮▮▮▮▮⚝ 使用 cache_.insert_or_assign(key, value)
将键值对插入或更新到 ConcurrentHashMap
中。
▮▮▮▮▮▮▮▮⚝ 使用 promise.setValue()
表示异步操作成功完成。
▮▮▮▮⚝ 返回 future
对象。
② main
函数:
▮▮▮▮⚝ 创建 IOThreadPoolExecutor
和 EventBase
对象。
▮▮▮▮⚝ 创建 AsyncCache
实例 cache
。
▮▮▮▮⚝ 设置缓存键 key
和值 value
。
▮▮▮▮⚝ 调用 cache.asyncSet
异步设置缓存。
▮▮▮▮⚝ 使用 setFuture.thenValue()
链式调用 cache.asyncGet
异步获取缓存。thenValue
的回调函数会在 setFuture
完成后执行,确保先设置缓存再获取缓存。
▮▮▮▮⚝ 使用 getFuture.thenValue()
和 getFuture.thenError()
处理缓存获取结果,打印成功或失败信息。
▮▮▮▮⚝ 异步获取一个不存在的键 "non_existent_key",并处理结果,预期会触发缓存未命中的异常。
▮▮▮▮⚝ 启动 EventBase
的事件循环 evb->loop()
。
编译和运行:
- 编译代码:使用支持 C++17 或更高版本的编译器编译上述代码,并链接
folly
库。编译命令示例:
1
g++ -std=c++17 async_cache.cpp -o async_cache -lfolly -lglog -pthread
- 运行程序:
1
./async_cache
1
程序运行后,将模拟异步缓存操作,并输出缓存设置和获取的结果。对于存在的键,将输出缓存值;对于不存在的键,将输出缓存未命中的错误信息。
缓存穿透、击穿、雪崩应对:
⚝ 缓存穿透(Cache Penetration):指查询不存在于缓存和数据库中的数据。为了避免频繁查询数据库,可以采用 布隆过滤器(Bloom Filter) 或 空值缓存 等策略。
⚝ 缓存击穿(Cache Breakdown):指热点缓存数据在过期时,大量请求同时访问该数据,导致请求直接穿透到数据库。可以使用 互斥锁(Mutex) 或 提前更新缓存 等策略。
⚝ 缓存雪崩(Cache Avalanche):指缓存系统大面积失效,导致所有请求都落到数据库,造成数据库压力过大甚至崩溃。可以使用 多级缓存、缓存预热、熔断限流 等策略。
folly::Future
可以与上述策略结合使用,构建更健壮、更可靠的异步缓存系统。例如,可以使用 Future::collect()
并行预热多个缓存项,使用 Future::within()
设置缓存操作的超时时间,使用 Future::recover()
在缓存未命中时异步回源数据库。
优势与应用场景:
⚝ 高并发访问:异步缓存系统可以处理大量并发缓存读写请求,提高缓存系统的吞吐量和并发处理能力。
⚝ 低延迟访问:异步缓存操作可以减少请求等待时间,提供更低的缓存访问延迟,提升应用程序的响应速度。
⚝ 资源高效利用:异步缓存避免线程阻塞等待缓存 I/O,可以更有效地利用系统资源,降低资源消耗。
适用场景:
⚝ Web 应用缓存:缓存 Web 页面、API 响应等数据,加速 Web 应用访问速度。
⚝ 数据库缓存:作为数据库的前置缓存,减轻数据库压力,提高数据访问性能。
⚝ 分布式缓存系统:构建分布式异步缓存系统,提供高可用、高扩展的缓存服务。
⚝ 消息队列缓存:缓存消息队列中的消息,提高消息消费速度。
总结:
本案例演示了如何使用 folly::Future
和 ConcurrentHashMap
构建一个简单的异步缓存系统。通过使用异步缓存和 folly
提供的异步编程工具,我们可以构建高性能、高并发的缓存系统,有效提升应用程序的性能和可扩展性。在实际应用中,需要根据具体的业务场景和性能需求,选择合适的缓存策略和数据结构,并结合 folly::Future
提供的丰富功能,构建更完善、更强大的异步缓存解决方案。
END_OF_CHAPTER
12. chapter 12: Future
API 全面解析 (Comprehensive API Analysis of Future
)
12.1 Future
类的方法详解 (Detailed Explanation of Future
Class Methods)
folly::Future<T>
是 folly/futures
库的核心组件,代表着异步操作的最终结果。它提供了一系列丰富的方法,用于检查 Future 的状态、获取结果、链式操作、错误处理、取消与超时控制等。本节将对 Future
类的常用方法进行详细的解析,帮助读者深入理解和灵活运用 Future
。
① 构造函数 (Constructors)
Future
类提供了多个构造函数,允许从不同的来源创建 Future
对象。
⚝ Future()
▮▮▮▮⚝ 函数签名:Future()
▮▮▮▮⚝ 描述:默认构造函数。创建一个空的 Future
对象,其状态为 未完成(Unready)
。通常与 Promise
配合使用,由 Promise
设置 Future
的最终结果。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Future<T>
对象
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> future;
6
std::cout << "Future is ready: " << future.isReady() << std::endl; // 输出: Future is ready: 0
7
return 0;
8
}
⚝ Future(Try<T>&& tryResult)
和 Future(Try<T> const& tryResult)
▮▮▮▮⚝ 函数签名:
▮▮▮▮▮▮▮▮⚝ Future(Try<T>&& tryResult)
▮▮▮▮▮▮▮▮⚝ Future(Try<T> const& tryResult)
▮▮▮▮⚝ 描述:从 folly::Try<T>
对象构造 Future
。Try<T>
可以封装一个值或一个异常。如果 Try<T>
包含值,则 Future
会立即完成并持有该值;如果 Try<T>
包含异常,则 Future
会立即完成并持有该异常。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ tryResult
:folly::Try<T>
对象,表示操作的结果(可能成功或失败)。
▮▮▮▮⚝ 返回值:Future<T>
对象
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Try.h>
3
#include <stdexcept>
4
#include <iostream>
5
6
int main() {
7
folly::Try<int> successTry = 42;
8
folly::Future<int> future1(std::move(successTry));
9
std::cout << "future1 value: " << future1.value() << std::endl; // 输出: future1 value: 42
10
11
folly::Try<int> failTry = std::runtime_error("Something went wrong");
12
folly::Future<int> future2(failTry);
13
try {
14
future2.value();
15
} catch (const std::exception& e) {
16
std::cout << "future2 exception: " << e.what() << std::endl; // 输出: future2 exception: Something went wrong
17
}
18
return 0;
19
}
⚝ Future(exception_ptr)
▮▮▮▮⚝ 函数签名:Future(exception_ptr)
▮▮▮▮⚝ 描述:从 std::exception_ptr
构造 Future
。Future
会立即完成并持有该异常。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ exceptionPtr
:std::exception_ptr
对象,表示一个异常。
▮▮▮▮⚝ 返回值:Future<T>
对象
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <stdexcept>
3
#include <iostream>
4
5
int main() {
6
std::exception_ptr exceptPtr = std::make_exception_ptr(std::runtime_error("Error from exception_ptr"));
7
folly::Future<int> future(exceptPtr);
8
try {
9
future.value();
10
} catch (const std::exception& e) {
11
std::cout << "future exception: " << e.what() << std::endl; // 输出: future exception: Error from exception_ptr
12
}
13
return 0;
14
}
⚝ Future(T&& value)
和 Future(T const& value)
▮▮▮▮⚝ 函数签名:
▮▮▮▮▮▮▮▮⚝ Future(T&& value)
▮▮▮▮▮▮▮▮⚝ Future(T const& value)
▮▮▮▮⚝ 描述:从值构造 Future
。Future
会立即完成并持有该值。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ value
:类型为 T
的值。
▮▮▮▮⚝ 返回值:Future<T>
对象
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> future1(100);
6
std::cout << "future1 value: " << future1.value() << std::endl; // 输出: future1 value: 100
7
8
int value = 200;
9
folly::Future<int> future2(value);
10
std::cout << "future2 value: " << future2.value() << std::endl; // 输出: future2 value: 200
11
return 0;
12
}
⚝ Future(SemiFuture<T>&& semiFuture)
和 Future(SemiFuture<T> const& semiFuture)
▮▮▮▮⚝ 函数签名:
▮▮▮▮▮▮▮▮⚝ Future(SemiFuture<T>&& semiFuture)
▮▮▮▮▮▮▮▮⚝ Future(SemiFuture<T> const& semiFuture)
▮▮▮▮⚝ 描述:从 folly::SemiFuture<T>
对象构造 Future
。SemiFuture
是 Future
的轻量级版本,通常用于性能敏感的场景。Future
会接管 SemiFuture
的状态。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ semiFuture
:folly::SemiFuture<T>
对象。
▮▮▮▮⚝ 返回值:Future<T>
对象
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/futures/SemiFuture.h>
3
#include <iostream>
4
5
int main() {
6
folly::Promise<int> promise;
7
folly::SemiFuture<int> semiFuture = promise.getSemiFuture();
8
folly::Future<int> future(std::move(semiFuture));
9
promise.setValue(500);
10
std::cout << "future value: " << future.value() << std::endl; // 输出: future value: 500
11
return 0;
12
}
⚝ Future(Future<T>&& other)
和 Future(Future<T> const& other)
▮▮▮▮⚝ 函数签名:
▮▮▮▮▮▮▮▮⚝ Future(Future<T>&& other)
▮▮▮▮▮▮▮▮⚝ Future(Future<T> const& other)
▮▮▮▮⚝ 描述:移动构造函数和拷贝构造函数。允许从另一个 Future
对象创建新的 Future
对象。移动构造函数会转移 other
的状态,拷贝构造函数会复制 other
的状态。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ other
:另一个 Future<T>
对象。
▮▮▮▮⚝ 返回值:Future<T>
对象
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> originalFuture = folly::makeFuture(1000);
6
folly::Future<int> movedFuture(std::move(originalFuture));
7
std::cout << "movedFuture value: " << movedFuture.value() << std::endl; // 输出: movedFuture value: 1000
8
9
folly::Future<int> copiedFuture(movedFuture); // 拷贝构造,movedFuture 仍然有效
10
std::cout << "copiedFuture value: " << copiedFuture.value() << std::endl; // 输出: copiedFuture value: 1000
11
return 0;
12
}
② 析构函数 (Destructor)
⚝ ~Future()
▮▮▮▮⚝ 函数签名:~Future()
▮▮▮▮⚝ 描述:析构函数。负责释放 Future
对象占用的资源。通常情况下,无需显式调用析构函数,当 Future
对象超出作用域时,会自动调用析构函数。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:无
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
3
void createFuture() {
4
folly::Future<int> future = folly::makeFuture(999);
5
// future 对象在函数结束时析构
6
}
7
8
int main() {
9
createFuture();
10
return 0;
11
}
③ 赋值运算符 (Assignment Operators)
⚝ operator=(Future<T>&& other)
和 operator=(Future<T> const& other)
▮▮▮▮⚝ 函数签名:
▮▮▮▮▮▮▮▮⚝ Future<T>& operator=(Future<T>&& other)
▮▮▮▮▮▮▮▮⚝ Future<T>& operator=(Future<T> const& other)
▮▮▮▮⚝ 描述:移动赋值运算符和拷贝赋值运算符。允许将一个 Future
对象赋值给另一个 Future
对象。移动赋值运算符会转移 other
的状态,拷贝赋值运算符会复制 other
的状态。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ other
:另一个 Future<T>
对象。
▮▮▮▮⚝ 返回值:Future<T>&
,返回对当前 Future
对象的引用。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> future1;
6
folly::Future<int> future2 = folly::makeFuture(555);
7
8
future1 = std::move(future2); // 移动赋值
9
std::cout << "future1 value: " << future1.value() << std::endl; // 输出: future1 value: 555
10
11
folly::Future<int> future3;
12
future3 = future1; // 拷贝赋值
13
std::cout << "future3 value: " << future3.value() << std::endl; // 输出: future3 value: 555
14
return 0;
15
}
④ 状态检查 (State Inspection)
⚝ isReady()
▮▮▮▮⚝ 函数签名:bool isReady() const
▮▮▮▮⚝ 描述:检查 Future
是否已完成(即,是否已设置值或异常)。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:bool
,true
如果 Future
已完成,false
否则。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> future = folly::makeFutureDelayed(std::chrono::milliseconds(100), 123);
6
std::cout << "Initial ready state: " << future.isReady() << std::endl; // 输出: Initial ready state: 0
7
std::this_thread::sleep_for(std::chrono::milliseconds(200));
8
std::cout << "Ready state after delay: " << future.isReady() << std::endl; // 输出: Ready state after delay: 1
9
return 0;
10
}
⚝ isCancelled()
▮▮▮▮⚝ 函数签名:bool isCancelled() const
▮▮▮▮⚝ 描述:检查 Future
是否已被取消。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:bool
,true
如果 Future
已被取消,false
否则。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Promise<int> promise;
6
folly::Future<int> future = promise.getFuture();
7
std::cout << "Initial cancelled state: " << future.isCancelled() << std::endl; // 输出: Initial cancelled state: 0
8
future.cancel();
9
std::cout << "Cancelled state after cancel(): " << future.isCancelled() << std::endl; // 输出: Cancelled state after cancel(): 1
10
return 0;
11
}
⚝ hasValue()
▮▮▮▮⚝ 函数签名:bool hasValue() const
▮▮▮▮⚝ 描述:检查 Future
是否已完成并持有一个值(而不是异常)。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:bool
,true
如果 Future
已完成且持有值,false
否则。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> valueFuture = folly::makeFuture(456);
6
folly::Future<int> exceptionFuture = folly::makeFutureError<int>(std::runtime_error("Test error"));
7
8
std::cout << "valueFuture hasValue: " << valueFuture.hasValue() << std::endl; // 输出: valueFuture hasValue: 1
9
std::cout << "exceptionFuture hasValue: " << exceptionFuture.hasValue() << std::endl; // 输出: exceptionFuture hasValue: 0
10
return 0;
11
}
⚝ hasException()
▮▮▮▮⚝ 函数签名:bool hasException() const
▮▮▮▮⚝ 描述:检查 Future
是否已完成并持有一个异常。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:bool
,true
如果 Future
已完成且持有异常,false
否则。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> valueFuture = folly::makeFuture(789);
6
folly::Future<int> exceptionFuture = folly::makeFutureError<int>(std::runtime_error("Another test error"));
7
8
std::cout << "valueFuture hasException: " << valueFuture.hasException() << std::endl; // 输出: valueFuture hasException: 0
9
std::cout << "exceptionFuture hasException: " << exceptionFuture.hasException() << std::endl; // 输出: exceptionFuture hasException: 1
10
return 0;
11
}
⚝ poll()
▮▮▮▮⚝ 函数签名:Optional<Try<T>> poll() const
▮▮▮▮⚝ 描述:非阻塞地检查 Future
的状态。如果 Future
已完成,则返回包含 Try<T>
的 Optional
对象,其中 Try<T>
封装了结果(值或异常);如果 Future
尚未完成,则返回空的 Optional
对象。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Optional<Try<T>>
,包含 Try<T>
的 Optional
对象或空的 Optional
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Optional.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> future = folly::makeFutureDelayed(std::chrono::milliseconds(100), 111);
7
folly::Optional<folly::Try<int>> result1 = future.poll();
8
std::cout << "Poll result before completion: " << result1.hasValue() << std::endl; // 输出: Poll result before completion: 0
9
10
std::this_thread::sleep_for(std::chrono::milliseconds(200));
11
folly::Optional<folly::Try<int>> result2 = future.poll();
12
std::cout << "Poll result after completion: " << result2.hasValue() << std::endl; // 输出: Poll result after completion: 1
13
std::cout << "Polled value: " << result2.value().value() << std::endl; // 输出: Polled value: 111
14
return 0;
15
}
⑤ 结果访问 (Result Access)
⚝ get()
▮▮▮▮⚝ 函数签名:T get() &&
和 T const& get() const&
▮▮▮▮⚝ 描述:同步等待 Future
完成并返回其结果。如果 Future
持有值,则返回该值;如果 Future
持有异常,则抛出该异常。这是一个阻塞操作,应谨慎使用,尤其是在异步环境中。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:T
,Future
持有的值。
▮▮▮▮⚝ 异常:如果 Future
持有异常,则抛出该异常。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <stdexcept>
4
5
int main() {
6
folly::Future<int> valueFuture = folly::makeFuture(1212);
7
int value = valueFuture.get();
8
std::cout << "get() value: " << value << std::endl; // 输出: get() value: 1212
9
10
folly::Future<int> exceptionFuture = folly::makeFutureError<int>(std::runtime_error("Get error"));
11
try {
12
exceptionFuture.get();
13
} catch (const std::exception& e) {
14
std::cout << "get() exception: " << e.what() << std::endl; // 输出: get() exception: Get error
15
}
16
return 0;
17
}
⚝ value()
▮▮▮▮⚝ 函数签名:T value() &&
和 T const& value() const&
▮▮▮▮⚝ 描述:尝试获取 Future
的值。仅当 Future
已完成且持有值时才能调用此方法。如果 Future
未完成或持有异常,则行为未定义(通常会抛出异常或导致程序崩溃,具体取决于编译配置)。通常应先使用 hasValue()
或 isReady()
检查 Future
的状态。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:T
,Future
持有的值。
▮▮▮▮⚝ 异常:如果 Future
未完成或持有异常,则行为未定义。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> valueFuture = folly::makeFuture(3434);
6
if (valueFuture.hasValue()) {
7
int value = valueFuture.value();
8
std::cout << "value() value: " << value << std::endl; // 输出: value() value: 3434
9
}
10
11
folly::Future<int> unreadyFuture;
12
// unreadyFuture.value(); // 避免直接调用未完成 Future 的 value(),行为未定义
13
14
return 0;
15
}
⚝ exception()
▮▮▮▮⚝ 函数签名:exception_ptr exception() &&
和 exception_ptr exception() const&
▮▮▮▮⚝ 描述:尝试获取 Future
的异常。仅当 Future
已完成且持有异常时才能调用此方法。如果 Future
未完成或持有值,则行为未定义。通常应先使用 hasException()
或 isReady()
检查 Future
的状态。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:std::exception_ptr
,Future
持有的异常指针。
▮▮▮▮⚝ 异常:如果 Future
未完成或持有值,则行为未定义。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> exceptionFuture = folly::makeFutureError<int>(std::runtime_error("Exception test"));
6
if (exceptionFuture.hasException()) {
7
std::exception_ptr exceptPtr = exceptionFuture.exception();
8
try {
9
std::rethrow_exception(exceptPtr);
10
} catch (const std::exception& e) {
11
std::cout << "exception() caught: " << e.what() << std::endl; // 输出: exception() caught: Exception test
12
}
13
}
14
15
folly::Future<int> valueFuture = folly::makeFuture(5656);
16
// valueFuture.exception(); // 避免直接调用持有值的 Future 的 exception(),行为未定义
17
18
return 0;
19
}
⚝ result()
▮▮▮▮⚝ 函数签名:Try<T> result() &&
和 Try<T> result() const&
▮▮▮▮⚝ 描述:尝试获取 Future
的结果,以 folly::Try<T>
对象的形式返回。仅当 Future
已完成时才能调用此方法。如果 Future
未完成,则行为未定义。Try<T>
对象封装了值或异常,可以通过 Try<T>
的方法来判断结果是值还是异常,并访问具体内容。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Try<T>
,封装了 Future
结果的 Try<T>
对象。
▮▮▮▮⚝ 异常:如果 Future
未完成,则行为未定义。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Try.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> valueFuture = folly::makeFuture(7878);
7
folly::Try<int> valueTry = valueFuture.result();
8
if (valueTry.hasValue()) {
9
std::cout << "result() value: " << valueTry.value() << std::endl; // 输出: result() value: 7878
10
}
11
12
folly::Future<int> exceptionFuture = folly::makeFutureError<int>(std::runtime_error("Result Try error"));
13
folly::Try<int> exceptionTry = exceptionFuture.result();
14
if (exceptionTry.hasException()) {
15
try {
16
exceptionTry.throwException();
17
} catch (const std::exception& e) {
18
std::cout << "result() exception: " << e.what() << std::endl; // 输出: result() exception: Result Try error
19
}
20
}
21
return 0;
22
}
⚝ tryGet()
▮▮▮▮⚝ 函数签名:Optional<Try<T>> tryGet() &&
和 Optional<Try<T>> tryGet() const&
▮▮▮▮⚝ 描述:非阻塞地尝试获取 Future
的结果。如果 Future
已完成,则返回包含 Try<T>
的 Optional
对象;如果 Future
尚未完成,则返回空的 Optional
对象。与 poll()
方法类似,但 tryGet()
的语义更侧重于“尝试获取结果”。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Optional<Try<T>>
,包含 Try<T>
的 Optional
对象或空的 Optional
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Optional.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> future = folly::makeFutureDelayed(std::chrono::milliseconds(100), 9090);
7
folly::Optional<folly::Try<int>> tryResult1 = future.tryGet();
8
std::cout << "tryGet() before completion: " << tryResult1.hasValue() << std::endl; // 输出: tryGet() before completion: 0
9
10
std::this_thread::sleep_for(std::chrono::milliseconds(200));
11
folly::Optional<folly::Try<int>> tryResult2 = future.tryGet();
12
std::cout << "tryGet() after completion: " << tryResult2.hasValue() << std::endl; // 输出: tryGet() after completion: 1
13
if (tryResult2.hasValue() && tryResult2.value().hasValue()) {
14
std::cout << "tryGet() value: " << tryResult2.value().value() << std::endl; // 输出: tryGet() value: 9090
15
}
16
return 0;
17
}
⑥ 链式操作与转换 (Chaining and Transformation)
Future
提供了丰富的链式操作方法,允许以异步的方式组合和转换 Future
。这些方法都返回新的 Future
对象,从而实现异步操作的流水线。
⚝ then()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto then(F&& f) &&;
3
4
template <typename F>
5
auto then(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
完成时,异步执行回调函数 f
。f
可以接受前一个 Future
的结果(Try<T>
)作为参数,并返回一个新的值、Future
或 SemiFuture
。then()
是构建异步操作链的核心方法。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:回调函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ R f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ R f(Try<T> const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(Try<T> const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(Try<T> const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,其类型取决于回调函数 f
的返回值类型。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
folly::Future<int> asyncTask(int input) {
5
return folly::makeFutureDelayed(std::chrono::milliseconds(50), input * 2);
6
}
7
8
int main() {
9
folly::Future<int> future1 = folly::makeFuture(10);
10
auto future2 = future1.then([](folly::Try<int>&& result) {
11
if (result.hasValue()) {
12
return asyncTask(result.value());
13
} else {
14
return folly::makeFutureError<int>(result.exception());
15
}
16
});
17
18
future2.then([](folly::Try<int>&& finalResult) {
19
if (finalResult.hasValue()) {
20
std::cout << "then() chain result: " << finalResult.value() << std::endl; // 输出: then() chain result: 20
21
} else {
22
std::cerr << "then() chain error: " << finalResult.exception().what() << std::endl;
23
}
24
return folly::Unit(); // then() 链的末尾通常返回 folly::Unit() 或 void
25
});
26
27
return 0;
28
}
⚝ thenValue()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto thenValue(F&& f) &&;
3
4
template <typename F>
5
auto thenValue(F&& f) const&;
▮▮▮▮⚝ 描述:类似于 then()
,但回调函数 f
只处理前一个 Future
的成功值(value)。如果前一个 Future
失败(持有异常),则 thenValue()
会直接传递异常到返回的 Future
。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:回调函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ R f(T&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ R f(T const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(T&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(T const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(T&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(T const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型,T
是前一个 Future
的值类型。
▮▮▮▮⚝ 返回值:一个新的 Future
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
folly::Future<int> asyncSquare(int input) {
5
return folly::makeFutureDelayed(std::chrono::milliseconds(50), input * input);
6
}
7
8
int main() {
9
folly::Future<int> future1 = folly::makeFuture(5);
10
auto future2 = future1.thenValue([](int value) {
11
return asyncSquare(value);
12
});
13
14
future2.thenValue([](int finalValue) {
15
std::cout << "thenValue() result: " << finalValue << std::endl; // 输出: thenValue() result: 25
16
return folly::Unit();
17
});
18
19
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("Value chain error"));
20
auto future3 = errorFuture.thenValue([](int value) { // 错误 Future 不会执行 thenValue 的回调
21
std::cout << "This should not be printed." << std::endl;
22
return folly::makeFuture(value * 2);
23
});
24
25
future3.then([](folly::Try<int>&& finalResult) {
26
if (finalResult.hasException()) {
27
std::cerr << "thenValue() error propagated: " << finalResult.exception().what() << std::endl; // 输出: thenValue() error propagated: Value chain error
28
}
29
return folly::Unit();
30
});
31
32
return 0;
33
}
⚝ thenError()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto thenError(F&& f) &&;
3
4
template <typename F>
5
auto thenError(F&& f) const&;
▮▮▮▮⚝ 描述:类似于 then()
,但回调函数 f
只处理前一个 Future
的异常(error)。如果前一个 Future
成功(持有值),则 thenError()
会直接传递值到返回的 Future
。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:回调函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ R f(exception_ptr)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(exception_ptr)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(exception_ptr)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型。
▮▮▮▮⚝ 返回值:一个新的 Future
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
folly::Future<int> asyncRecover(std::exception_ptr error) {
5
std::cerr << "Recovering from error: " << error.what() << std::endl;
6
return folly::makeFutureDelayed(std::chrono::milliseconds(50), -1); // 返回一个默认值
7
}
8
9
int main() {
10
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("Initial error"));
11
auto future2 = errorFuture.thenError([](std::exception_ptr error) {
12
return asyncRecover(error);
13
});
14
15
future2.thenValue([](int recoveredValue) {
16
std::cout << "thenError() recovered value: " << recoveredValue << std::endl; // 输出: thenError() recovered value: -1
17
return folly::Unit();
18
});
19
20
folly::Future<int> valueFuture = folly::makeFuture(100);
21
auto future3 = valueFuture.thenError([](std::exception_ptr error) { // 成功 Future 不会执行 thenError 的回调
22
std::cout << "This should not be printed." << std::endl;
23
return folly::makeFuture(0);
24
});
25
26
future3.thenValue([](int originalValue) {
27
std::cout << "thenError() value propagated: " << originalValue << std::endl; // 输出: thenError() value propagated: 100
28
return folly::Unit();
29
});
30
31
return 0;
32
}
⚝ thenTry()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto thenTry(F&& f) &&;
3
4
template <typename F>
5
auto thenTry(F&& f) const&;
▮▮▮▮⚝ 描述:类似于 then()
,回调函数 f
处理前一个 Future
的 Try<T>
结果,无论成功或失败。thenTry()
提供了最通用的链式操作方式,可以同时处理值和异常。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:回调函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ R f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ R f(Try<T> const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(Try<T> const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(Try<T> const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型,Try<T>
是前一个 Future
的结果。
▮▮▮▮⚝ 返回值:一个新的 Future
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
folly::Future<int> asyncProcessTry(folly::Try<int>&& inputTry) {
5
if (inputTry.hasValue()) {
6
return folly::makeFutureDelayed(std::chrono::milliseconds(50), inputTry.value() + 10);
7
} else {
8
std::cerr << "Processing try, got error: " << inputTry.exception().what() << std::endl;
9
return folly::makeFutureError<int>(std::runtime_error("Processed error"));
10
}
11
}
12
13
int main() {
14
folly::Future<int> future1 = folly::makeFuture(20);
15
auto future2 = future1.thenTry([](folly::Try<int>&& tryResult) {
16
return asyncProcessTry(std::move(tryResult));
17
});
18
19
future2.thenTry([](folly::Try<int>&& finalTry) {
20
if (finalTry.hasValue()) {
21
std::cout << "thenTry() success result: " << finalTry.value() << std::endl; // 输出: thenTry() success result: 30
22
} else {
23
std::cerr << "thenTry() final error: " << finalTry.exception().what() << std::endl;
24
}
25
return folly::Unit();
26
});
27
28
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("Try chain initial error"));
29
auto future3 = errorFuture.thenTry([](folly::Try<int>&& tryResult) {
30
return asyncProcessTry(std::move(tryResult)); // 错误 Future 仍然会执行 thenTry 的回调
31
});
32
33
future3.thenTry([](folly::Try<int>&& finalTry) {
34
if (finalTry.hasException()) {
35
std::cerr << "thenTry() error processed and propagated: " << finalTry.exception().what() << std::endl; // 输出: thenTry() error processed and propagated: Processed error
36
}
37
return folly::Unit();
38
});
39
40
return 0;
41
}
⚝ map()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto map(F&& f) &&;
3
4
template <typename F>
5
auto map(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
成功完成时,同步地转换其值。如果前一个 Future
失败,则 map()
会直接传递异常到返回的 Future
。map()
适用于同步的值转换操作。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:转换函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ R f(T&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ R f(T const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型,T
是前一个 Future
的值类型。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有转换后的值或原始异常。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int syncDouble(int value) {
5
return value * 2;
6
}
7
8
int main() {
9
folly::Future<int> future1 = folly::makeFuture(30);
10
auto future2 = future1.map(syncDouble);
11
12
future2.thenValue([](int mappedValue) {
13
std::cout << "map() result: " << mappedValue << std::endl; // 输出: map() result: 60
14
return folly::Unit();
15
});
16
17
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("Map error"));
18
auto future3 = errorFuture.map(syncDouble); // 错误 Future 不会执行 map 的转换函数
19
20
future3.then([](folly::Try<int>&& finalResult) {
21
if (finalResult.hasException()) {
22
std::cerr << "map() error propagated: " << finalResult.exception().what() << std::endl; // 输出: map() error propagated: Map error
23
}
24
return folly::Unit();
25
});
26
27
return 0;
28
}
⚝ mapValue()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto mapValue(F&& f) &&;
3
4
template <typename F>
5
auto mapValue(F&& f) const&;
▮▮▮▮⚝ 描述:与 map()
功能相同,是 map()
的别名,为了更清晰地表达“映射值”的意图。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:转换函数或函数对象,与 map()
的 f
参数相同。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,与 map()
的返回值相同。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
std::string syncToString(int value) {
5
return std::to_string(value);
6
}
7
8
int main() {
9
folly::Future<int> future1 = folly::makeFuture(40);
10
auto future2 = future1.mapValue(syncToString);
11
12
future2.thenValue([](const std::string& stringValue) {
13
std::cout << "mapValue() result: " << stringValue << std::endl; // 输出: mapValue() result: 40
14
return folly::Unit();
15
});
16
17
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("MapValue error"));
18
auto future3 = errorFuture.mapValue(syncToString); // 错误 Future 不会执行 mapValue 的转换函数
19
20
future3.then([](folly::Try<std::string>&& finalResult) {
21
if (finalResult.hasException()) {
22
std::cerr << "mapValue() error propagated: " << finalResult.exception().what() << std::endl; // 输出: mapValue() error propagated: MapValue error
23
}
24
return folly::Unit();
25
});
26
27
return 0;
28
}
⚝ mapError()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto mapError(F&& f) &&;
3
4
template <typename F>
5
auto mapError(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
失败时,同步地转换其异常。如果前一个 Future
成功,则 mapError()
会直接传递值到返回的 Future
。mapError()
适用于同步的异常转换或包装操作。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:转换函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ exception_ptr f(exception_ptr)
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有原始值或转换后的异常。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <stdexcept>
4
5
std::exception_ptr syncWrapError(std::exception_ptr error) {
6
return std::make_exception_ptr(std::runtime_error(std::string("Wrapped error: ") + error.what()));
7
}
8
9
int main() {
10
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("Original error"));
11
auto future2 = errorFuture.mapError(syncWrapError);
12
13
future2.then([](folly::Try<int>&& finalResult) {
14
if (finalResult.hasException()) {
15
try {
16
std::rethrow_exception(finalResult.exception());
17
} catch (const std::exception& e) {
18
std::cerr << "mapError() wrapped error: " << e.what() << std::endl; // 输出: mapError() wrapped error: Wrapped error: Original error
19
}
20
}
21
return folly::Unit();
22
});
23
24
folly::Future<int> valueFuture = folly::makeFuture(50);
25
auto future3 = valueFuture.mapError(syncWrapError); // 成功 Future 不会执行 mapError 的转换函数
26
27
future3.thenValue([](int originalValue) {
28
std::cout << "mapError() value propagated: " << originalValue << std::endl; // 输出: mapError() value propagated: 50
29
return folly::Unit();
30
});
31
32
return 0;
33
}
⚝ mapTry()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto mapTry(F&& f) &&;
3
4
template <typename F>
5
auto mapTry(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
完成时,同步地转换其 Try<T>
结果(值或异常)。mapTry()
提供了最通用的同步转换方式,可以同时处理值和异常。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:转换函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Try<R> f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Try<R> f(Try<T> const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型,Try<T>
是前一个 Future
的结果。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有转换后的 Try<R>
结果。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Try.h>
3
#include <iostream>
4
#include <stdexcept>
5
6
folly::Try<int> syncProcessTryResult(folly::Try<int>&& inputTry) {
7
if (inputTry.hasValue()) {
8
return folly::Try<int>(inputTry.value() * 3);
9
} else {
10
return folly::Try<int>(std::make_exception_ptr(std::runtime_error(std::string("Processed Try error: ") + inputTry.exception().what())));
11
}
12
}
13
14
int main() {
15
folly::Future<int> future1 = folly::makeFuture(60);
16
auto future2 = future1.mapTry(syncProcessTryResult);
17
18
future2.thenTry([](folly::Try<int>&& finalTry) {
19
if (finalTry.hasValue()) {
20
std::cout << "mapTry() success result: " << finalTry.value() << std::endl; // 输出: mapTry() success result: 180
21
} else {
22
std::cerr << "mapTry() processed error: " << finalTry.exception().what() << std::endl;
23
}
24
return folly::Unit();
25
});
26
27
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("MapTry initial error"));
28
auto future3 = errorFuture.mapTry(syncProcessTryResult); // 错误 Future 仍然会执行 mapTry 的转换函数
29
30
future3.thenTry([](folly::Try<int>&& finalTry) {
31
if (finalTry.hasException()) {
32
std::cerr << "mapTry() error processed and propagated: " << finalTry.exception().what() << std::endl; // 输出: mapTry() error processed and propagated: Processed Try error: MapTry initial error
33
}
34
return folly::Unit();
35
});
36
37
return 0;
38
}
⚝ flatMap()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto flatMap(F&& f) &&;
3
4
template <typename F>
5
auto flatMap(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
成功完成时,异步地转换其值,并且展平返回的 Future
。回调函数 f
必须返回一个 Future
或 SemiFuture
。flatMap()
用于处理嵌套的异步操作,避免产生 Future<Future<T>>
类型。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:转换函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(T&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(T const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(T&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(T const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型,T
是前一个 Future
的值类型。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有展平后的异步操作结果。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
folly::Future<int> asyncIncrement(int value) {
5
return folly::makeFutureDelayed(std::chrono::milliseconds(50), value + 1);
6
}
7
8
int main() {
9
folly::Future<int> future1 = folly::makeFuture(70);
10
auto future2 = future1.flatMap(asyncIncrement); // 返回 Future<int> 而不是 Future<Future<int>>
11
12
future2.thenValue([](int flatMappedValue) {
13
std::cout << "flatMap() result: " << flatMappedValue << std::endl; // 输出: flatMap() result: 71
14
return folly::Unit();
15
});
16
17
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("FlatMap error"));
18
auto future3 = errorFuture.flatMap(asyncIncrement); // 错误 Future 不会执行 flatMap 的转换函数
19
20
future3.then([](folly::Try<int>&& finalResult) {
21
if (finalResult.hasException()) {
22
std::cerr << "flatMap() error propagated: " << finalResult.exception().what() << std::endl; // 输出: flatMap() error propagated: FlatMap error
23
}
24
return folly::Unit();
25
});
26
27
return 0;
28
}
⚝ flatMapValue()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto flatMapValue(F&& f) &&;
3
4
template <typename F>
5
auto flatMapValue(F&& f) const&;
▮▮▮▮⚝ 描述:与 flatMap()
功能相同,是 flatMap()
的别名,为了更清晰地表达“扁平化映射值”的意图。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:转换函数或函数对象,与 flatMap()
的 f
参数相同。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,与 flatMap()
的返回值相同。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
folly::Future<std::string> asyncToStringFuture(int value) {
5
return folly::makeFutureDelayed(std::chrono::milliseconds(50), std::to_string(value));
6
}
7
8
int main() {
9
folly::Future<int> future1 = folly::makeFuture(80);
10
auto future2 = future1.flatMapValue(asyncToStringFuture);
11
12
future2.thenValue([](const std::string& stringValue) {
13
std::cout << "flatMapValue() result: " << stringValue << std::endl; // 输出: flatMapValue() result: 80
14
return folly::Unit();
15
});
16
17
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("FlatMapValue error"));
18
auto future3 = errorFuture.flatMapValue(asyncToStringFuture); // 错误 Future 不会执行 flatMapValue 的转换函数
19
20
future3.then([](folly::Try<std::string>&& finalResult) {
21
if (finalResult.hasException()) {
22
std::cerr << "flatMapValue() error propagated: " << finalResult.exception().what() << std::endl; // 输出: flatMapValue() error propagated: FlatMapValue error
23
}
24
return folly::Unit();
25
});
26
27
return 0;
28
}
⚝ flatMapError()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto flatMapError(F&& f) &&;
3
4
template <typename F>
5
auto flatMapError(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
失败时,异步地转换其异常,并且展平返回的 Future
。回调函数 f
必须返回一个 Future
或 SemiFuture
。flatMapError()
用于异步的异常恢复或替换操作。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:转换函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(exception_ptr)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(exception_ptr)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有展平后的异步异常处理结果。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
folly::Future<int> asyncRecoverWithValue(std::exception_ptr error) {
5
std::cerr << "Recovering from flatMapError: " << error.what() << std::endl;
6
return folly::makeFutureDelayed(std::chrono::milliseconds(50), 999); // 异步返回一个恢复值
7
}
8
9
int main() {
10
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("FlatMapError initial error"));
11
auto future2 = errorFuture.flatMapError(asyncRecoverWithValue);
12
13
future2.thenValue([](int recoveredValue) {
14
std::cout << "flatMapError() recovered value: " << recoveredValue << std::endl; // 输出: flatMapError() recovered value: 999
15
return folly::Unit();
16
});
17
18
folly::Future<int> valueFuture = folly::makeFuture(90);
19
auto future3 = valueFuture.flatMapError([](std::exception_ptr error) { // 成功 Future 不会执行 flatMapError 的转换函数
20
std::cout << "This should not be printed." << std::endl;
21
return folly::makeFuture(0);
22
});
23
24
future3.thenValue([](int originalValue) {
25
std::cout << "flatMapError() value propagated: " << originalValue << std::endl; // 输出: flatMapError() value propagated: 90
26
return folly::Unit();
27
});
28
29
return 0;
30
}
⚝ flatMapTry()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto flatMapTry(F&& f) &&;
3
4
template <typename F>
5
auto flatMapTry(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
完成时,异步地转换其 Try<T>
结果,并且展平返回的 Future
。回调函数 f
必须返回一个 Future
或 SemiFuture
。flatMapTry()
提供了最通用的异步展平转换方式,可以同时处理值和异常。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:转换函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(Try<T> const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(Try<T> const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型,Try<T>
是前一个 Future
的结果。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有展平后的异步操作结果。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
folly::Future<int> asyncProcessAndIncrementTry(folly::Try<int>&& inputTry) {
5
if (inputTry.hasValue()) {
6
return folly::makeFutureDelayed(std::chrono::milliseconds(50), inputTry.value() + 1);
7
} else {
8
std::cerr << "flatMapTry processing error: " << inputTry.exception().what() << std::endl;
9
return folly::makeFutureError<int>(std::runtime_error("flatMapTry processed error"));
10
}
11
}
12
13
int main() {
14
folly::Future<int> future1 = folly::makeFuture(100);
15
auto future2 = future1.flatMapTry([](folly::Try<int>&& tryResult) {
16
return asyncProcessAndIncrementTry(std::move(tryResult));
17
});
18
19
future2.thenValue([](int flatMappedTryValue) {
20
std::cout << "flatMapTry() success result: " << flatMappedTryValue << std::endl; // 输出: flatMapTry() success result: 101
21
return folly::Unit();
22
});
23
24
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("FlatMapTry initial error"));
25
auto future3 = errorFuture.flatMapTry([](folly::Try<int>&& tryResult) {
26
return asyncProcessAndIncrementTry(std::move(tryResult)); // 错误 Future 仍然会执行 flatMapTry 的转换函数
27
});
28
29
future3.thenTry([](folly::Try<int>&& finalTry) {
30
if (finalTry.hasException()) {
31
std::cerr << "flatMapTry() error processed and propagated: " << finalTry.exception().what() << std::endl; // 输出: flatMapTry() error processed and propagated: flatMapTry processed error
32
}
33
return folly::Unit();
34
});
35
36
return 0;
37
}
⚝ unit()
▮▮▮▮⚝ 函数签名:
1
folly::Future<folly::Unit> unit() &&;
2
folly::Future<folly::Unit> unit() const&;
▮▮▮▮⚝ 描述:将 Future<T>
转换为 Future<folly::Unit>
。如果原始 Future
成功,则返回的 Future
也成功,但不携带任何值(folly::Unit
表示空值);如果原始 Future
失败,则返回的 Future
也失败,并携带相同的异常。unit()
常用于忽略 Future
的值,只关心其完成状态。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Future<folly::Unit>
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Unit.h>
3
#include <iostream>
4
5
folly::Future<int> asyncOperation() {
6
return folly::makeFutureDelayed(std::chrono::milliseconds(50), 12345);
7
}
8
9
int main() {
10
folly::Future<int> future1 = asyncOperation();
11
auto unitFuture1 = future1.unit();
12
13
unitFuture1.thenValue([](folly::Unit) {
14
std::cout << "unit() success, value ignored." << std::endl; // 输出: unit() success, value ignored.
15
return folly::Unit();
16
});
17
18
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("Unit error"));
19
auto unitFuture2 = errorFuture.unit();
20
21
unitFuture2.then([](folly::Try<folly::Unit>&& finalTry) {
22
if (finalTry.hasException()) {
23
std::cerr << "unit() error propagated: " << finalTry.exception().what() << std::endl; // 输出: unit() error propagated: Unit error
24
}
25
return folly::Unit();
26
});
27
28
return 0;
29
}
⚝ error()
▮▮▮▮⚝ 函数签名:
1
folly::Future<std::exception_ptr> error() &&;
2
folly::Future<std::exception_ptr> error() const&;
▮▮▮▮⚝ 描述:将 Future<T>
转换为 Future<std::exception_ptr>
。如果原始 Future
成功,则返回的 Future
失败,并携带一个 BrokenPromise
异常;如果原始 Future
失败,则返回的 Future
成功,并持有原始的异常。error()
常用于将成功结果转换为错误信号,或提取 Future
的异常。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Future<std::exception_ptr>
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <folly/exception_wrappers.h>
4
5
folly::Future<int> asyncOperationWithValue() {
6
return folly::makeFutureDelayed(std::chrono::milliseconds(50), 54321);
7
}
8
9
int main() {
10
folly::Future<int> future1 = asyncOperationWithValue();
11
auto errorFuture1 = future1.error();
12
13
errorFuture1.thenValue([](std::exception_ptr errorPtr) {
14
try {
15
std::rethrow_exception(errorPtr);
16
} catch (const folly::BrokenPromise& e) {
17
std::cout << "error() success converted to BrokenPromise error." << std::endl; // 输出: error() success converted to BrokenPromise error.
18
} catch (...) {
19
std::cerr << "Unexpected exception type." << std::endl;
20
}
21
return folly::Unit();
22
});
23
24
folly::Future<int> originalErrorFuture = folly::makeFutureError<int>(std::runtime_error("Original Error for error()"));
25
auto errorFuture2 = originalErrorFuture.error();
26
27
errorFuture2.thenValue([](std::exception_ptr errorPtr) {
28
try {
29
std::rethrow_exception(errorPtr);
30
} catch (const std::exception& e) {
31
std::cerr << "error() error propagated: " << e.what() << std::endl; // 输出: error() error propagated: Original Error for error()
32
}
33
return folly::Unit();
34
});
35
36
return 0;
37
}
⚝ withValue()
▮▮▮▮⚝ 函数签名:
1
folly::Future<folly::Try<T>> withValue() &&;
2
folly::Future<folly::Try<T>> withValue() const&;
▮▮▮▮⚝ 描述:将 Future<T>
转换为 Future<Try<T>>
。如果原始 Future
成功,则返回的 Future
也成功,并持有 Try<T>
对象,该 Try<T>
对象包含原始的值;如果原始 Future
失败,则返回的 Future
也失败,并持有 Try<T>
对象,该 Try<T>
对象包含原始的异常。withValue()
常用于将 Future
的结果包装在 Try<T>
中,方便后续统一处理成功和失败的情况。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Future<folly::Try<T>>
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Try.h>
3
#include <iostream>
4
5
folly::Future<int> asyncValueOperation() {
6
return folly::makeFutureDelayed(std::chrono::milliseconds(50), 67890);
7
}
8
9
int main() {
10
folly::Future<int> future1 = asyncValueOperation();
11
auto tryFuture1 = future1.withValue();
12
13
tryFuture1.thenValue([](folly::Try<int> tryResult) {
14
if (tryResult.hasValue()) {
15
std::cout << "withValue() success, Try value: " << tryResult.value() << std::endl; // 输出: withValue() success, Try value: 67890
16
} else {
17
std::cerr << "withValue() unexpected error." << std::endl;
18
}
19
return folly::Unit();
20
});
21
22
folly::Future<int> originalErrorFuture = folly::makeFutureError<int>(std::runtime_error("WithValue Error"));
23
auto tryFuture2 = originalErrorFuture.withValue();
24
25
tryFuture2.thenValue([](folly::Try<int> tryResult) {
26
if (tryResult.hasException()) {
27
try {
28
tryResult.throwException();
29
} catch (const std::exception& e) {
30
std::cerr << "withValue() error propagated in Try: " << e.what() << std::endl; // 输出: withValue() error propagated in Try: WithValueError
31
}
32
} else {
33
std::cerr << "withValue() unexpected success." << std::endl;
34
}
35
return folly::Unit();
36
});
37
38
return 0;
39
}
⚝ withException()
▮▮▮▮⚝ 函数签名:
1
folly::Future<folly::Try<T>> withException() &&;
2
folly::Future<folly::Try<T>> withException() const&;
▮▮▮▮⚝ 描述:与 withValue()
功能相同,是 withValue()
的别名,为了更清晰地表达“包含异常”的意图。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Future<folly::Try<T>>
对象,与 withValue()
的返回值相同。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Try.h>
3
#include <iostream>
4
5
folly::Future<int> asyncExceptionOperation() {
6
return folly::makeFutureDelayed<int>(std::chrono::milliseconds(50), [](){ throw std::runtime_error("Async operation error"); });
7
}
8
9
int main() {
10
folly::Future<int> future1 = asyncExceptionOperation();
11
auto tryFuture1 = future1.withException();
12
13
tryFuture1.thenValue([](folly::Try<int> tryResult) {
14
if (tryResult.hasException()) {
15
try {
16
tryResult.throwException();
17
} catch (const std::exception& e) {
18
std::cerr << "withException() error in Try: " << e.what() << std::endl; // 输出: withException() error in Try: Async operation error
19
}
20
} else {
21
std::cerr << "withException() unexpected success." << std::endl;
22
}
23
return folly::Unit();
24
});
25
26
folly::Future<int> originalValueFuture = folly::makeFuture(11111);
27
auto tryFuture2 = originalValueFuture.withException();
28
29
tryFuture2.thenValue([](folly::Try<int> tryResult) {
30
if (tryResult.hasValue()) {
31
std::cout << "withException() success in Try: " << tryResult.value() << std::endl; // 输出: withException() success in Try: 11111
32
} else {
33
std::cerr << "withException() unexpected error." << std::endl;
34
}
35
return folly::Unit();
36
});
37
38
return 0;
39
}
⚝ withTry()
▮▮▮▮⚝ 函数签名:
1
folly::Future<folly::Try<T>> withTry() &&;
2
folly::Future<folly::Try<T>> withTry() const&;
▮▮▮▮⚝ 描述:与 withValue()
和 withException()
功能相同,是它们的别名,为了更通用地表达“包含 Try
结果”的意图。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Future<folly::Try<T>>
对象,与 withValue()
和 withException()
的返回值相同。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Try.h>
3
#include <iostream>
4
5
folly::Future<int> asyncTryOperation(bool shouldFail) {
6
if (shouldFail) {
7
return folly::makeFutureDelayed<int>(std::chrono::milliseconds(50), [](){ throw std::runtime_error("Async Try operation error"); });
8
} else {
9
return folly::makeFutureDelayed(std::chrono::milliseconds(50), 22222);
10
}
11
}
12
13
int main() {
14
folly::Future<int> future1 = asyncTryOperation(true);
15
auto tryFuture1 = future1.withTry();
16
17
tryFuture1.thenValue([](folly::Try<int> tryResult) {
18
if (tryResult.hasException()) {
19
try {
20
tryResult.throwException();
21
} catch (const std::exception& e) {
22
std::cerr << "withTry() error in Try: " << e.what() << std::endl; // 输出: withTry() error in Try: Async Try operation error
23
}
24
} else {
25
std::cerr << "withTry() unexpected success." << std::endl;
26
}
27
return folly::Unit();
28
});
29
30
folly::Future<int> future2 = asyncTryOperation(false);
31
auto tryFuture2 = future2.withTry();
32
33
tryFuture2.thenValue([](folly::Try<int> tryResult) {
34
if (tryResult.hasValue()) {
35
std::cout << "withTry() success in Try: " << tryResult.value() << std::endl; // 输出: withTry() success in Try: 22222
36
} else {
37
std::cerr << "withTry() unexpected error." << std::endl;
38
}
39
return folly::Unit();
40
});
41
42
return 0;
43
}
⚝ catchError()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto catchError(F&& f) &&;
3
4
template <typename F>
5
auto catchError(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
失败时,同步地捕获并处理异常。如果前一个 Future
成功,则 catchError()
会直接传递值到返回的 Future
。回调函数 f
必须返回一个值或抛出异常。catchError()
用于同步的异常处理和恢复。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:异常处理函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ T f(exception_ptr)
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有处理后的值或原始值(如果未发生错误)。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int syncRecoverValue(std::exception_ptr error) {
5
std::cerr << "catchError() recovering from error: " << error.what() << std::endl;
6
return -99; // 返回一个默认值
7
}
8
9
int main() {
10
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("CatchError initial error"));
11
auto future2 = errorFuture.catchError(syncRecoverValue);
12
13
future2.thenValue([](int recoveredValue) {
14
std::cout << "catchError() recovered value: " << recoveredValue << std::endl; // 输出: catchError() recovered value: -99
15
return folly::Unit();
16
});
17
18
folly::Future<int> valueFuture = folly::makeFuture(33333);
19
auto future3 = valueFuture.catchError(syncRecoverValue); // 成功 Future 不会执行 catchError 的处理函数
20
21
future3.thenValue([](int originalValue) {
22
std::cout << "catchError() value propagated: " << originalValue << std::endl; // 输出: catchError() value propagated: 33333
23
return folly::Unit();
24
});
25
26
return 0;
27
}
⚝ catchErrorOfType<E>()
▮▮▮▮⚝ 函数签名:
1
template <typename E, typename F>
2
auto catchErrorOfType(F&& f) &&;
3
4
template <typename E, typename F>
5
auto catchErrorOfType(F&& f) const&;
▮▮▮▮⚝ 描述:类似于 catchError()
,但只捕获特定类型的异常 E
。如果捕获到类型为 E
的异常,则调用回调函数 f
进行处理;如果捕获到其他类型的异常或 Future
成功,则传递原始结果到返回的 Future
。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ E
:要捕获的异常类型。
▮▮▮▮▮▮▮▮⚝ f
:异常处理函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ T f(E&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ T f(E const&)
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有处理后的值或原始值/异常。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <stdexcept>
4
5
int syncRecoverSpecificError(const std::runtime_error& error) {
6
std::cerr << "catchErrorOfType() recovering from runtime_error: " << error.what() << std::endl;
7
return -77; // 返回一个特定错误类型的默认值
8
}
9
10
int main() {
11
folly::Future<int> runtimeErrorFuture = folly::makeFutureError<int>(std::runtime_error("Runtime error to catch"));
12
auto future2 = runtimeErrorFuture.catchErrorOfType<std::runtime_error>(syncRecoverSpecificError);
13
14
future2.thenValue([](int recoveredValue) {
15
std::cout << "catchErrorOfType() recovered value (runtime_error): " << recoveredValue << std::endl; // 输出: catchErrorOfType() recovered value (runtime_error): -77
16
return folly::Unit();
17
});
18
19
folly::Future<int> logicErrorFuture = folly::makeFutureError<int>(std::logic_error("Logic error not caught"));
20
auto future3 = logicErrorFuture.catchErrorOfType<std::runtime_error>(syncRecoverSpecificError); // logic_error 不会被 catchErrorOfType<std::runtime_error> 捕获
21
22
future3.then([](folly::Try<int>&& finalTry) {
23
if (finalTry.hasException()) {
24
try {
25
finalTry.throwException();
26
} catch (const std::exception& e) {
27
std::cerr << "catchErrorOfType() error propagated (logic_error): " << e.what() << std::endl; // 输出: catchErrorOfType() error propagated (logic_error): Logic error not caught
28
}
29
}
30
return folly::Unit();
31
});
32
33
folly::Future<int> valueFuture = folly::makeFuture(44444);
34
auto future4 = valueFuture.catchErrorOfType<std::runtime_error>(syncRecoverSpecificError); // 成功 Future 不会执行 catchErrorOfType 的处理函数
35
36
future4.thenValue([](int originalValue) {
37
std::cout << "catchErrorOfType() value propagated: " << originalValue << std::endl; // 输出: catchErrorOfType() value propagated: 44444
38
return folly::Unit();
39
});
40
41
return 0;
42
}
⚝ catchTry()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto catchTry(F&& f) &&;
3
4
template <typename F>
5
auto catchTry(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
失败时,同步地捕获并处理异常,回调函数 f
接受 Try<T>
对象作为参数。如果前一个 Future
成功,则 catchTry()
会直接传递值到返回的 Future
。catchTry()
提供了更灵活的同步异常处理方式,可以根据 Try<T>
对象判断是否发生错误,并进行相应的处理。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:异常处理函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Try<T> f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Try<T> f(Try<T> const&)
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有处理后的 Try<T>
结果或原始值。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Try.h>
3
#include <iostream>
4
#include <stdexcept>
5
6
folly::Try<int> syncProcessTryAndRecover(folly::Try<int>&& inputTry) {
7
if (inputTry.hasException()) {
8
std::cerr << "catchTry() processing error: " << inputTry.exception().what() << std::endl;
9
return folly::Try<int>(-55); // 返回一个 Try<int> 封装的默认值
10
} else {
11
return inputTry; // 成功时直接返回原始 Try
12
}
13
}
14
15
int main() {
16
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("CatchTry initial error"));
17
auto future2 = errorFuture.catchTry(syncProcessTryAndRecover);
18
19
future2.thenTry([](folly::Try<int>&& finalTry) {
20
if (finalTry.hasValue()) {
21
std::cout << "catchTry() recovered value: " << finalTry.value() << std::endl; // 输出: catchTry() recovered value: -55
22
} else {
23
std::cerr << "catchTry() unexpected error after recovery." << std::endl;
24
}
25
return folly::Unit();
26
});
27
28
folly::Future<int> valueFuture = folly::makeFuture(55555);
29
auto future3 = valueFuture.catchTry(syncProcessTryAndRecover); // 成功 Future 不会执行 catchTry 的异常处理逻辑
30
31
future3.thenTry([](folly::Try<int>&& finalTry) {
32
if (finalTry.hasValue()) {
33
std::cout << "catchTry() value propagated: " << finalTry.value() << std::endl; // 输出: catchTry() value propagated: 55555
34
} else {
35
std::cerr << "catchTry() unexpected error propagation." << std::endl;
36
}
37
return folly::Unit();
38
});
39
40
return 0;
41
}
⚝ recover()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto recover(F&& f) &&;
3
4
template <typename F>
5
auto recover(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
失败时,异步地从异常中恢复。回调函数 f
必须返回一个值、Future
或 SemiFuture
。如果前一个 Future
成功,则 recover()
会直接传递值到返回的 Future
。recover()
用于异步的异常恢复操作。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:恢复函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ R f(exception_ptr)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(exception_ptr)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(exception_ptr)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有恢复后的值或原始值(如果未发生错误)。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
folly::Future<int> asyncDefaultValue(std::exception_ptr error) {
5
std::cerr << "recover() async recovering from error: " << error.what() << std::endl;
6
return folly::makeFutureDelayed(std::chrono::milliseconds(50), -100); // 异步返回一个默认值
7
}
8
9
int main() {
10
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("Recover initial error"));
11
auto future2 = errorFuture.recover(asyncDefaultValue);
12
13
future2.thenValue([](int recoveredValue) {
14
std::cout << "recover() recovered value: " << recoveredValue << std::endl; // 输出: recover() recovered value: -100
15
return folly::Unit();
16
});
17
18
folly::Future<int> valueFuture = folly::makeFuture(66666);
19
auto future3 = valueFuture.recover(asyncDefaultValue); // 成功 Future 不会执行 recover 的恢复函数
20
21
future3.thenValue([](int originalValue) {
22
std::cout << "recover() value propagated: " << originalValue << std::endl; // 输出: recover() value propagated: 66666
23
return folly::Unit();
24
});
25
26
return 0;
27
}
⚝ recoverWith()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto recoverWith(F&& f) &&;
3
4
template <typename F>
5
auto recoverWith(F&& f) const&;
▮▮▮▮⚝ 描述:与 recover()
功能相同,是 recover()
的别名,为了更清晰地表达“使用...恢复”的意图。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:恢复函数或函数对象,与 recover()
的 f
参数相同。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,与 recover()
的返回值相同。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
folly::Future<int> asyncBackupOperation(std::exception_ptr error) {
5
std::cerr << "recoverWith() using backup operation for error: " << error.what() << std::endl;
6
return folly::makeFutureDelayed(std::chrono::milliseconds(50), 77777); // 异步执行备份操作
7
}
8
9
int main() {
10
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("RecoverWith initial error"));
11
auto future2 = errorFuture.recoverWith(asyncBackupOperation);
12
13
future2.thenValue([](int recoveredValue) {
14
std::cout << "recoverWith() recovered value: " << recoveredValue << std::endl; // 输出: recoverWith() recovered value: 77777
15
return folly::Unit();
16
});
17
18
folly::Future<int> valueFuture = folly::makeFuture(88888);
19
auto future3 = valueFuture.recoverWith(asyncBackupOperation); // 成功 Future 不会执行 recoverWith 的备份操作
20
21
future3.thenValue([](int originalValue) {
22
std::cout << "recoverWith() value propagated: " << originalValue << std::endl; // 输出: recoverWith() value propagated: 88888
23
return folly::Unit();
24
});
25
26
return 0;
27
}
⚝ recoverTry()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto recoverTry(F&& f) &&;
3
4
template <typename F>
5
auto recoverTry(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
失败时,异步地从异常中恢复,回调函数 f
接受 Try<T>
对象作为参数。回调函数 f
必须返回一个 Future
或 SemiFuture
。recoverTry()
提供了最灵活的异步异常恢复方式,可以根据 Try<T>
对象判断是否发生错误,并进行相应的恢复操作。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:恢复函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f(Try<T> const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(Try<T>&&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f(Try<T> const&)
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型,Try<T>
是前一个 Future
的结果。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有恢复后的异步操作结果或原始值。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Try.h>
3
#include <iostream>
4
5
folly::Future<int> asyncProcessTryAndRecoverValue(folly::Try<int>&& inputTry) {
6
if (inputTry.hasException()) {
7
std::cerr << "recoverTry() async processing error: " << inputTry.exception().what() << std::endl;
8
return folly::makeFutureDelayed(std::chrono::milliseconds(50), -200); // 异步返回一个 Try<int> 封装的默认值
9
} else {
10
return folly::makeFuture(inputTry.value()); // 成功时直接返回原始值 Future
11
}
12
}
13
14
int main() {
15
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("RecoverTry initial error"));
16
auto future2 = errorFuture.recoverTry([](folly::Try<int>&& tryResult) {
17
return asyncProcessTryAndRecoverValue(std::move(tryResult));
18
});
19
20
future2.thenValue([](int recoveredValue) {
21
std::cout << "recoverTry() recovered value: " << recoveredValue << std::endl; // 输出: recoverTry() recovered value: -200
22
return folly::Unit();
23
});
24
25
folly::Future<int> valueFuture = folly::makeFuture(99999);
26
auto future3 = valueFuture.recoverTry([](folly::Try<int>&& tryResult) {
27
return asyncProcessTryAndRecoverValue(std::move(tryResult)); // 成功 Future 不会执行 recoverTry 的异常恢复逻辑
28
});
29
30
future3.thenValue([](int originalValue) {
31
std::cout << "recoverTry() value propagated: " << originalValue << std::endl; // 输出: recoverTry() value propagated: 99999
32
return folly::Unit();
33
});
34
35
return 0;
36
}
⚝ ensure()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto ensure(F&& f) &&;
3
4
template <typename F>
5
auto ensure(F&& f) const&;
▮▮▮▮⚝ 描述:当 Future
完成时(无论成功或失败),同步地执行回调函数 f
。ensure()
常用于执行清理操作,例如释放资源、记录日志等,确保这些操作在 Future
完成后一定会执行。回调函数 f
不影响 Future
的结果,它只用于执行副作用操作。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:回调函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ void f()
▮▮▮▮⚝ 返回值:一个新的 Future
对象,持有与原始 Future
相同的结果(值或异常)。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
void syncCleanup() {
5
std::cout << "ensure() performing cleanup." << std::endl;
6
}
7
8
int main() {
9
folly::Future<int> future1 = folly::makeFuture(123);
10
auto future2 = future1.ensure(syncCleanup);
11
12
future2.thenValue([](int originalValue) {
13
std::cout << "ensure() original value: " << originalValue << std::endl; // 输出: ensure() original value: 123
14
return folly::Unit();
15
});
16
17
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("Ensure error"));
18
auto future3 = errorFuture.ensure(syncCleanup);
19
20
future3.then([](folly::Try<int>&& finalTry) {
21
if (finalTry.hasException()) {
22
try {
23
finalTry.throwException();
24
} catch (const std::exception& e) {
25
std::cerr << "ensure() error propagated: " << e.what() << std::endl; // 输出: ensure() error propagated: Ensure error
26
}
27
}
28
return folly::Unit();
29
});
30
31
return 0;
32
}
⚝ finally()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto finally(F&& f) &&;
3
4
template <typename F>
5
auto finally(F&& f) const&;
▮▮▮▮⚝ 描述:与 ensure()
功能相同,是 ensure()
的别名,为了更清晰地表达“最终执行”的意图。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:回调函数或函数对象,与 ensure()
的 f
参数相同。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,与 ensure()
的返回值相同。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
void syncFinalAction() {
5
std::cout << "finally() executing final action." << std::endl;
6
}
7
8
int main() {
9
folly::Future<int> future1 = folly::makeFuture(456);
10
auto future2 = future1.finally(syncFinalAction);
11
12
future2.thenValue([](int originalValue) {
13
std::cout << "finally() original value: " << originalValue << std::endl; // 输出: finally() original value: 456
14
return folly::Unit();
15
});
16
17
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("Finally error"));
18
auto future3 = errorFuture.finally(syncFinalAction);
19
20
future3.then([](folly::Try<int>&& finalTry) {
21
if (finalTry.hasException()) {
22
try {
23
finalTry.throwException();
24
} catch (const std::exception& e) {
25
std::cerr << "finally() error propagated: " << e.what() << std::endl; // 输出: finally() error propagated: Finally error
26
}
27
}
28
return folly::Unit();
29
});
30
31
return 0;
32
}
⚝ within()
▮▮▮▮⚝ 函数签名:
1
folly::Future<T> within(Duration duration) &&;
2
folly::Future<T> within(Duration duration) const&;
3
folly::Future<T> within(TimePoint tp) &&;
4
folly::Future<T> within(TimePoint tp) const&;
▮▮▮▮⚝ 描述:设置 Future
的超时时间。如果在指定的时间内 Future
未完成,则返回的 Future
会失败,并携带 std::future_error
异常,错误码为 std::future_errc::timeout
。within()
用于控制异步操作的执行时间,防止无限期等待。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ duration
:超时时长,例如 std::chrono::milliseconds(100)
.
▮▮▮▮▮▮▮▮⚝ tp
:超时时间点,例如 std::chrono::steady_clock::now() + std::chrono::seconds(1)
.
▮▮▮▮⚝ 返回值:一个新的 Future
对象,具有超时控制。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <chrono>
4
#include <stdexcept>
5
#include <system_error>
6
7
folly::Future<int> longRunningTask() {
8
return folly::makeFutureDelayed(std::chrono::seconds(1), 123); // 模拟一个耗时操作
9
}
10
11
int main() {
12
folly::Future<int> future1 = longRunningTask();
13
auto timeoutFuture1 = future1.within(std::chrono::milliseconds(500)); // 设置 500ms 超时
14
15
timeoutFuture1.thenTry([](folly::Try<int>&& finalTry) {
16
if (finalTry.hasValue()) {
17
std::cout << "within() success, value: " << finalTry.value() << std::endl;
18
} else if (finalTry.hasException()) {
19
try {
20
finalTry.throwException();
21
} catch (const std::future_error& e) {
22
if (e.code() == std::future_errc::timeout) {
23
std::cerr << "within() timeout error caught." << std::endl; // 输出: within() timeout error caught.
24
} else {
25
std::cerr << "within() other future_error: " << e.what() << std::endl;
26
}
27
} catch (const std::exception& e) {
28
std::cerr << "within() other error: " << e.what() << std::endl;
29
}
30
}
31
return folly::Unit();
32
});
33
34
folly::Future<int> quickTask = folly::makeFuture(456);
35
auto timeoutFuture2 = quickTask.within(std::chrono::seconds(2)); // 设置 2s 超时,足够完成
36
37
timeoutFuture2.thenValue([](int value) {
38
std::cout << "within() success within time, value: " << value << std::endl; // 输出: within() success within time, value: 456
39
return folly::Unit();
40
});
41
42
return 0;
43
}
⚝ onTimeout()
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto onTimeout(Duration duration, F&& f) &&;
3
4
template <typename F>
5
auto onTimeout(Duration duration, F&& f) const&;
6
7
template <typename F>
8
auto onTimeout(TimePoint tp, F&& f) &&;
9
10
template <typename F>
11
auto onTimeout(TimePoint tp, F&& f) const&;
▮▮▮▮⚝ 描述:设置 Future
的超时处理回调函数。如果在指定的时间内 Future
未完成,则异步执行回调函数 f
。回调函数 f
可以返回一个新的值、Future
或 SemiFuture
,用于提供超时时的默认值或执行备用操作。如果 onTimeout()
的回调函数没有执行,则超时不会发生,原始 Future
的结果会被传递下去。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ duration
:超时时长。
▮▮▮▮▮▮▮▮⚝ tp
:超时时间点。
▮▮▮▮▮▮▮▮⚝ f
:超时回调函数或函数对象。其签名可以是:
▮▮▮▮▮▮▮▮▮▮▮▮⚝ R f()
▮▮▮▮▮▮▮▮▮▮▮▮⚝ Future<R> f()
▮▮▮▮▮▮▮▮▮▮▮▮⚝ SemiFuture<R> f()
▮▮▮▮▮▮▮▮▮▮▮▮⚝ 其中 R
是返回值类型。
▮▮▮▮⚝ 返回值:一个新的 Future
对象,具有超时处理逻辑。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <chrono>
4
5
folly::Future<int> longTaskForTimeout() {
6
return folly::makeFutureDelayed(std::chrono::seconds(1), 789); // 模拟耗时任务
7
}
8
9
folly::Future<int> timeoutFallbackValue() {
10
std::cerr << "onTimeout() timeout occurred, using fallback value." << std::endl;
11
return folly::makeFuture(0); // 超时时返回默认值 0
12
}
13
14
int main() {
15
folly::Future<int> future1 = longTaskForTimeout();
16
auto timeoutFuture1 = future1.onTimeout(std::chrono::milliseconds(500), timeoutFallbackValue); // 500ms 超时回调
17
18
timeoutFuture1.thenValue([](int value) {
19
std::cout << "onTimeout() result value: " << value << std::endl; // 输出: onTimeout() result value: 0 (fallback value)
20
return folly::Unit();
21
});
22
23
folly::Future<int> quickTaskForTimeout = folly::makeFuture(101112);
24
auto timeoutFuture2 = quickTaskForTimeout.onTimeout(std::chrono::seconds(2), timeoutFallbackValue); // 2s 超时,任务足够完成
25
26
timeoutFuture2.thenValue([](int value) {
27
std::cout << "onTimeout() success within time, value: " << value << std::endl; // 输出: onTimeout() success within time, value: 101112
28
return folly::Unit();
29
});
30
31
return 0;
32
}
⚝ raise()
▮▮▮▮⚝ 函数签名:
1
folly::Future<T> raise() &&;
2
folly::Future<T> raise() const&;
▮▮▮▮⚝ 描述:如果 Future
成功完成,则将其转换为失败的 Future
,并携带 BrokenPromise
异常;如果 Future
已经失败,则保持失败状态不变。raise()
常用于强制将成功结果转换为错误信号。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:一个新的 Future
对象,可能转换为失败状态。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <folly/exception_wrappers.h>
4
5
int main() {
6
folly::Future<int> successFuture = folly::makeFuture(131415);
7
auto raisedFuture1 = successFuture.raise();
8
9
raisedFuture1.then([](folly::Try<int>&& finalTry) {
10
if (finalTry.hasException()) {
11
try {
12
finalTry.throwException();
13
} catch (const folly::BrokenPromise& e) {
14
std::cerr << "raise() success converted to BrokenPromise error." << std::endl; // 输出: raise() success converted to BrokenPromise error.
15
} catch (...) {
16
std::cerr << "raise() unexpected exception type." << std::endl;
17
}
18
}
19
return folly::Unit();
20
});
21
22
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("Raise original error"));
23
auto raisedFuture2 = errorFuture.raise(); // 错误 Future 调用 raise() 保持错误状态
24
25
raisedFuture2.then([](folly::Try<int>&& finalTry) {
26
if (finalTry.hasException()) {
27
try {
28
finalTry.throwException();
29
} catch (const std::exception& e) {
30
std::cerr << "raise() error propagated: " << e.what() << std::endl; // 输出: raise() error propagated: Raise original error
31
}
32
}
33
return folly::Unit();
34
});
35
36
return 0;
37
}
⚝ forwardException()
▮▮▮▮⚝ 函数签名:
1
folly::Future<T> forwardException() &&;
2
folly::Future<T> forwardException() const&;
▮▮▮▮⚝ 描述:如果 Future
成功完成,则将其转换为失败的 Future
,并携带 BrokenPromise
异常;如果 Future
已经失败,则保持失败状态不变。与 raise()
功能相同,是 raise()
的别名,为了更清晰地表达“转发异常”的意图。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:一个新的 Future
对象,可能转换为失败状态,与 raise()
的返回值相同。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <folly/exception_wrappers.h>
4
5
int main() {
6
folly::Future<int> successFuture = folly::makeFuture(161718);
7
auto forwardedFuture1 = successFuture.forwardException();
8
9
forwardedFuture1.then([](folly::Try<int>&& finalTry) {
10
if (finalTry.hasException()) {
11
try {
12
finalTry.throwException();
13
} catch (const folly::BrokenPromise& e) {
14
std::cerr << "forwardException() success converted to BrokenPromise error." << std::endl; // 输出: forwardException() success converted to BrokenPromise error.
15
} catch (...) {
16
std::cerr << "forwardException() unexpected exception type." << std::endl;
17
}
18
}
19
return folly::Unit();
20
});
21
22
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("ForwardException original error"));
23
auto forwardedFuture2 = errorFuture.forwardException(); // 错误 Future 调用 forwardException() 保持错误状态
24
25
forwardedFuture2.then([](folly::Try<int>&& finalTry) {
26
if (finalTry.hasException()) {
27
try {
28
finalTry.throwException();
29
} catch (const std::exception& e) {
30
std::cerr << "forwardException() error propagated: " << e.what() << std::endl; // 输出: forwardException() error propagated: ForwardException original error
31
}
32
}
33
return folly::Unit();
34
});
35
36
return 0;
37
}
⑦ 取消与中断 (Cancellation and Interruption)
⚝ cancel()
▮▮▮▮⚝ 函数签名:void cancel()
▮▮▮▮⚝ 描述:取消 Future
。取消操作是协作式的,需要异步操作本身支持取消。取消后,Future
会进入取消状态,后续对其进行链式操作可能会被短路或抛出 CancelledException
。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:void
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <folly/exception_wrappers.h>
4
5
int main() {
6
folly::Promise<int> promise;
7
folly::Future<int> future = promise.getFuture();
8
9
future.cancel(); // 取消 Future
10
11
future.then([](folly::Try<int>&& finalTry) {
12
if (finalTry.hasException()) {
13
try {
14
finalTry.throwException();
15
} catch (const folly::CancelledException& e) {
16
std::cerr << "cancel() caught CancelledException." << std::endl; // 输出: cancel() caught CancelledException.
17
} catch (...) {
18
std::cerr << "cancel() unexpected exception type." << std::endl;
19
}
20
} else {
21
std::cerr << "cancel() unexpected success." << std::endl;
22
}
23
return folly::Unit();
24
});
25
26
return 0;
27
}
⚝ setInterruptible(bool interruptible = true)
▮▮▮▮⚝ 函数签名:folly::Future<T>& setInterruptible(bool interruptible = true)
▮▮▮▮⚝ 描述:设置 Future
是否可中断。如果设置为可中断,则可以通过外部机制(例如信号处理)中断 Future
的等待操作(如 get()
, wait()
等)。默认情况下,Future
是不可中断的。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ interruptible
:bool
值,true
表示可中断,false
表示不可中断,默认为 true
。
▮▮▮▮⚝ 返回值:folly::Future<T>&
,返回对当前 Future
对象的引用。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <thread>
4
#include <csignal>
5
6
void signalHandler(int signum) {
7
std::cerr << "Interrupt signal (" << signum << ") received.\n";
8
// 在实际应用中,可能需要更复杂的信号处理逻辑
9
}
10
11
int main() {
12
std::signal(SIGINT, signalHandler); // 注册信号处理函数
13
14
folly::Promise<int> promise;
15
folly::Future<int> future = promise.getFuture();
16
future.setInterruptible(); // 设置 Future 为可中断
17
18
std::thread waitThread([&future]() {
19
try {
20
future.get(); // 同步等待 Future 结果,可能被中断
21
} catch (const folly::CancelledException& e) {
22
std::cerr << "get() interrupted by CancelledException." << std::endl;
23
} catch (const std::exception& e) {
24
std::cerr << "get() exception: " << e.what() << std::endl;
25
}
26
});
27
28
std::this_thread::sleep_for(std::chrono::milliseconds(100));
29
promise.setValue(192021); // 设置 Future 值,正常情况下 waitThread 会获取到结果
30
// 或者,可以发送中断信号来中断 waitThread 的等待
31
// std::raise(SIGINT);
32
33
waitThread.join();
34
return 0;
35
}
⚝ isInterruptible()
▮▮▮▮⚝ 函数签名:bool isInterruptible() const
▮▮▮▮⚝ 描述:检查 Future
是否设置为可中断。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:bool
,true
如果 Future
可中断,false
否则。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> future1 = folly::makeFuture(123);
6
std::cout << "future1 isInterruptible (default): " << future1.isInterruptible() << std::endl; // 输出: future1 isInterruptible (default): 0
7
8
folly::Future<int> future2 = folly::makeFuture(456);
9
future2.setInterruptible();
10
std::cout << "future2 isInterruptible (after setInterruptible): " << future2.isInterruptible() << std::endl; // 输出: future2 isInterruptible (after setInterruptible): 1
11
12
return 0;
13
}
⑧ 同步等待 (Synchronous Waiting)
⚝ wait()
▮▮▮▮⚝ 函数签名:
1
void wait() &&;
2
void wait() const&;
3
bool wait(Duration duration) &&;
4
bool wait(Duration duration) const&;
5
bool wait(TimePoint tp) &&;
6
bool wait(TimePoint tp) const&;
▮▮▮▮⚝ 描述:同步等待 Future
完成。wait()
的不同重载版本允许无限期等待,或设置超时时间。这是一个阻塞操作,应谨慎使用,尤其是在异步环境中。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ duration
:等待时长,例如 std::chrono::milliseconds(100)
.
▮▮▮▮▮▮▮▮⚝ tp
:等待截止时间点,例如 std::chrono::steady_clock::now() + std::chrono::seconds(1)
.
▮▮▮▮⚝ 返回值:
▮▮▮▮▮▮▮▮⚝ void wait()
和 void wait() const&
: 无返回值。
▮▮▮▮▮▮▮▮⚝ bool wait(Duration duration)
、bool wait(Duration duration) const&
、bool wait(TimePoint tp)
、bool wait(TimePoint tp) const&
: bool
值,true
如果在超时时间内 Future
完成,false
如果超时。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <chrono>
4
5
folly::Future<int> delayedTaskForWait() {
6
return folly::makeFutureDelayed(std::chrono::milliseconds(200), 242526);
7
}
8
9
int main() {
10
folly::Future<int> future1 = delayedTaskForWait();
11
std::cout << "wait() before wait: isReady=" << future1.isReady() << std::endl; // 输出: wait() before wait: isReady=0
12
future1.wait(); // 无限期等待
13
std::cout << "wait() after wait: isReady=" << future1.isReady() << std::endl; // 输出: wait() after wait: isReady=1
14
15
folly::Future<int> future2 = delayedTaskForWait();
16
std::cout << "wait(duration) before wait: isReady=" << future2.isReady() << std::endl; // 输出: wait(duration) before wait: isReady=0
17
bool completedWithinTime = future2.wait(std::chrono::milliseconds(300)); // 设置 300ms 超时
18
std::cout << "wait(duration) after wait: isReady=" << future2.isReady() << ", completedWithinTime=" << completedWithinTime << std::endl; // 输出: wait(duration) after wait: isReady=1, completedWithinTime=1
19
20
folly::Future<int> future3 = delayedTaskForWait();
21
std::cout << "wait(timepoint) before wait: isReady=" << future3.isReady() << std::endl; // 输出: wait(timepoint) before wait: isReady=0
22
std::chrono::steady_clock::time_point timeoutTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
23
bool completedBeforeTimeout = future3.wait(timeoutTime); // 设置时间点超时,但超时时间较短,会超时
24
std::cout << "wait(timepoint) after wait: isReady=" << future3.isReady() << ", completedBeforeTimeout=" << completedBeforeTimeout << std::endl; // 输出: wait(timepoint) after wait: isReady=0, completedBeforeTimeout=0 (可能,取决于实际执行速度)
25
26
return 0;
27
}
⚝ waitUnlessCancelled()
▮▮▮▮⚝ 函数签名:
1
void waitUnlessCancelled() &&;
2
void waitUnlessCancelled() const&;
3
bool waitUnlessCancelled(Duration duration) &&;
4
bool waitUnlessCancelled(Duration duration) const&;
5
bool waitUnlessCancelled(TimePoint tp) &&;
6
bool waitUnlessCancelled(TimePoint tp) const&;
▮▮▮▮⚝ 描述:同步等待 Future
完成,但如果 Future
被取消,则立即返回,不会无限期等待。waitUnlessCancelled()
的不同重载版本允许无限期等待(直到取消或完成),或设置超时时间。这是一个阻塞操作,应谨慎使用。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ duration
:等待时长。
▮▮▮▮▮▮▮▮⚝ tp
:等待截止时间点。
▮▮▮▮⚝ 返回值:
▮▮▮▮▮▮▮▮⚝ void waitUnlessCancelled()
和 void waitUnlessCancelled() const&
: 无返回值。
▮▮▮▮▮▮▮▮⚝ bool waitUnlessCancelled(Duration duration)
、bool waitUnlessCancelled(Duration duration) const&
、bool waitUnlessCancelled(TimePoint tp)
、bool waitUnlessCancelled(TimePoint tp) const&
: bool
值,true
如果在超时时间内 Future
完成,false
如果超时或被取消。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <chrono>
4
#include <thread>
5
6
int main() {
7
folly::Promise<int> promise;
8
folly::Future<int> future = promise.getFuture();
9
10
std::thread cancelThread([&promise, &future]() {
11
std::this_thread::sleep_for(std::chrono::milliseconds(100));
12
future.cancel(); // 100ms 后取消 Future
13
});
14
15
std::cout << "waitUnlessCancelled() before wait: isReady=" << future.isReady() << ", isCancelled=" << future.isCancelled() << std::endl; // 输出: waitUnlessCancelled() before wait: isReady=0, isCancelled=0
16
future.waitUnlessCancelled(); // 无限期等待,直到完成或取消
17
std::cout << "waitUnlessCancelled() after wait: isReady=" << future.isReady() << ", isCancelled=" << future.isCancelled() << std::endl; // 输出: waitUnlessCancelled() after wait: isReady=0, isCancelled=1 (可能,取决于取消和完成的竞争)
18
19
cancelThread.join();
20
21
folly::Promise<int> promise2;
22
folly::Future<int> future2 = promise2.getFuture();
23
std::thread completeThread([&promise2]() {
24
std::this_thread::sleep_for(std::chrono::milliseconds(200));
25
promise2.setValue(272829); // 200ms 后完成 Future
26
});
27
28
std::cout << "waitUnlessCancelled(duration) before wait: isReady=" << future2.isReady() << ", isCancelled=" << future2.isCancelled() << std::endl; // 输出: waitUnlessCancelled(duration) before wait: isReady=0, isCancelled=0
29
bool completedOrCancelledWithinTime = future2.waitUnlessCancelled(std::chrono::milliseconds(300)); // 300ms 超时
30
std::cout << "waitUnlessCancelled(duration) after wait: isReady=" << future2.isReady() << ", isCancelled=" << future2.isCancelled() << ", completedOrCancelledWithinTime=" << completedOrCancelledWithinTime << std::endl; // 输出: waitUnlessCancelled(duration) after wait: isReady=1, isCancelled=0, completedOrCancelledWithinTime=1 (可能)
31
32
completeThread.join();
33
34
return 0;
35
}
⑨ 转换为其他类型 (Conversion to Other Types)
⚝ semi()
▮▮▮▮⚝ 函数签名:folly::SemiFuture<T> semi() &&
和 folly::SemiFuture<T> semi() const&
▮▮▮▮⚝ 描述:将 Future<T>
转换为 SemiFuture<T>
。SemiFuture
是 Future
的轻量级版本,具有更低的开销,但功能相对较少。转换后的 SemiFuture
会共享原始 Future
的状态。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:SemiFuture<T>
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/futures/SemiFuture.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> future = folly::makeFuture(303132);
7
folly::SemiFuture<int> semiFuture = future.semi();
8
9
semiFuture.thenValue([](int value) {
10
std::cout << "semi() SemiFuture value: " << value << std::endl; // 输出: semi() SemiFuture value: 303132
11
return folly::Unit();
12
});
13
14
return 0;
15
}
⚝ share()
▮▮▮▮⚝ 函数签名:folly::SharedFuture<T> share() &&
和 folly::SharedFuture<T> share() const&
▮▮▮▮⚝ 描述:将 Future<T>
转换为 SharedFuture<T>
。SharedFuture
允许多个观察者共享同一个 Future
的结果,每个观察者都可以独立地等待和获取结果。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:SharedFuture<T>
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/futures/SharedFuture.h>
3
#include <iostream>
4
#include <thread>
5
#include <vector>
6
7
int main() {
8
folly::Future<int> future = folly::makeFutureDelayed(std::chrono::milliseconds(100), 333435);
9
folly::SharedFuture<int> sharedFuture = future.share();
10
11
std::vector<std::thread> threads;
12
for (int i = 0; i < 3; ++i) {
13
threads.emplace_back([sharedFuture, i]() {
14
sharedFuture.thenValue([i](int value) {
15
std::cout << "SharedFuture thread " << i << " value: " << value << std::endl; // 输出: SharedFuture thread 0/1/2 value: 333435 (每个线程都会输出)
16
return folly::Unit();
17
});
18
});
19
}
20
21
for (auto& thread : threads) {
22
thread.join();
23
}
24
25
return 0;
26
}
⑩ 结果分离 (Result Detachment)
⚝ detachValue()
▮▮▮▮⚝ 函数签名:Optional<T> detachValue() &&
▮▮▮▮⚝ 描述:尝试分离 Future
的值。如果 Future
已完成且持有值,则返回包含该值的 Optional
对象,并将 Future
的状态重置为未完成;否则,返回空的 Optional
对象。detachValue()
只能调用一次,后续调用行为未定义。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Optional<T>
,包含值的 Optional
对象或空的 Optional
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Optional.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> future1 = folly::makeFuture(363738);
7
folly::Optional<int> detachedValue1 = future1.detachValue();
8
if (detachedValue1.hasValue()) {
9
std::cout << "detachValue() value: " << detachedValue1.value() << std::endl; // 输出: detachValue() value: 363738
10
}
11
std::cout << "future1 isReady after detachValue(): " << future1.isReady() << std::endl; // 输出: future1 isReady after detachValue(): 0
12
13
folly::Future<int> unreadyFuture;
14
folly::Optional<int> detachedValue2 = unreadyFuture.detachValue();
15
std::cout << "detachValue() on unready Future: " << detachedValue2.hasValue() << std::endl; // 输出: detachValue() on unready Future: 0
16
17
return 0;
18
}
⚝ detachException()
▮▮▮▮⚝ 函数签名:Optional<exception_ptr> detachException() &&
▮▮▮▮⚝ 描述:尝试分离 Future
的异常。如果 Future
已完成且持有异常,则返回包含该异常的 Optional
对象,并将 Future
的状态重置为未完成;否则,返回空的 Optional
对象。detachException()
只能调用一次,后续调用行为未定义。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Optional<exception_ptr>
,包含异常的 Optional
对象或空的 Optional
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Optional.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("DetachException error"));
7
folly::Optional<std::exception_ptr> detachedException1 = errorFuture.detachException();
8
if (detachedException1.hasValue()) {
9
try {
10
std::rethrow_exception(detachedException1.value());
11
} catch (const std::exception& e) {
12
std::cerr << "detachException() caught error: " << e.what() << std::endl; // 输出: detachException() caught error: DetachException error
13
}
14
}
15
std::cout << "errorFuture isReady after detachException(): " << errorFuture.isReady() << std::endl; // 输出: errorFuture isReady after detachException(): 0
16
17
folly::Future<int> valueFuture = folly::makeFuture(394041);
18
folly::Optional<std::exception_ptr> detachedException2 = valueFuture.detachException();
19
std::cout << "detachException() on value Future: " << detachedException2.hasValue() << std::endl; // 输出: detachException() on value Future: 0
20
21
return 0;
22
}
⚝ detachTry()
▮▮▮▮⚝ 函数签名:Optional<Try<T>> detachTry() &&
▮▮▮▮⚝ 描述:尝试分离 Future
的 Try<T>
结果。如果 Future
已完成,则返回包含 Try<T>
的 Optional
对象,并将 Future
的状态重置为未完成;否则,返回空的 Optional
对象。detachTry()
只能调用一次,后续调用行为未定义。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Optional<Try<T>>
,包含 Try<T>
的 Optional
对象或空的 Optional
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Optional.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> future1 = folly::makeFuture(424344);
7
folly::Optional<folly::Try<int>> detachedTry1 = future1.detachTry();
8
if (detachedTry1.hasValue() && detachedTry1.value().hasValue()) {
9
std::cout << "detachTry() value: " << detachedTry1.value().value() << std::endl; // 输出: detachTry() value: 424344
10
}
11
std::cout << "future1 isReady after detachTry(): " << future1.isReady() << std::endl; // 输出: future1 isReady after detachTry(): 0
12
13
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("DetachTry error"));
14
folly::Optional<folly::Try<int>> detachedTry2 = errorFuture.detachTry();
15
if (detachedTry2.hasValue() && detachedTry2.value().hasException()) {
16
try {
17
detachedTry2.value().throwException();
18
} catch (const std::exception& e) {
19
std::cerr << "detachTry() caught error: " << e.what() << std::endl; // 输出: detachTry() caught error: DetachTry error
20
}
21
}
22
std::cout << "errorFuture isReady after detachTry(): " << errorFuture.isReady() << std::endl; // 输出: errorFuture isReady after detachTry(): 0
23
24
return 0;
25
}
⚝ detachResult()
▮▮▮▮⚝ 函数签名:Optional<Try<T>> detachResult() &&
▮▮▮▮⚝ 描述:与 detachTry()
功能相同,是 detachTry()
的别名,为了更清晰地表达“分离结果”的意图。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Optional<Try<T>>
,与 detachTry()
的返回值相同。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Optional.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> future1 = folly::makeFuture(454647);
7
folly::Optional<folly::Try<int>> detachedResult1 = future1.detachResult();
8
if (detachedResult1.hasValue() && detachedResult1.value().hasValue()) {
9
std::cout << "detachResult() value: " << detachedResult1.value().value() << std::endl; // 输出: detachResult() value: 454647
10
}
11
std::cout << "future1 isReady after detachResult(): " << future1.isReady() << std::endl; // 输出: future1 isReady after detachResult(): 0
12
13
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("DetachResult error"));
14
folly::Optional<folly::Try<int>> detachedResult2 = errorFuture.detachResult();
15
if (detachedResult2.hasValue() && detachedResult2.value().hasException()) {
16
try {
17
detachedResult2.value().throwException();
18
} catch (const std::exception& e) {
19
std::cerr << "detachResult() caught error: " << e.what() << std::endl; // 输出: detachResult() caught error: DetachResult error
20
}
21
}
22
std::cout << "errorFuture isReady after detachResult(): " << errorFuture.isReady() << std::endl; // 输出: errorFuture isReady after detachResult(): 0
23
24
return 0;
25
}
⑪ 移动结果 (Moving Result)
⚝ moveResult()
▮▮▮▮⚝ 函数签名:Try<T> moveResult() &&
▮▮▮▮⚝ 描述:移动提取 Future
的 Try<T>
结果。与 detachTry()
类似,但 moveResult()
返回的是 Try<T>
对象本身,而不是 Optional<Try<T>>
。调用 moveResult()
后,Future
的状态会被重置为未完成。moveResult()
只能调用一次,后续调用行为未定义。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Try<T>
,Future
的 Try<T>
结果。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Try.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> future1 = folly::makeFuture(484950);
7
folly::Try<int> movedResult1 = future1.moveResult();
8
if (movedResult1.hasValue()) {
9
std::cout << "moveResult() value: " << movedResult1.value() << std::endl; // 输出: moveResult() value: 484950
10
}
11
std::cout << "future1 isReady after moveResult(): " << future1.isReady() << std::endl; // 输出: future1 isReady after moveResult(): 0
12
13
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("MoveResult error"));
14
folly::Try<int> movedResult2 = errorFuture.moveResult();
15
if (movedResult2.hasException()) {
16
try {
17
movedResult2.throwException();
18
} catch (const std::exception& e) {
19
std::cerr << "moveResult() caught error: " << e.what() << std::endl; // 输出: moveResult() caught error: MoveResult error
20
}
21
}
22
std::cout << "errorFuture isReady after moveResult(): " << errorFuture.isReady() << std::endl; // 输出: errorFuture isReady after moveResult(): 0
23
24
return 0;
25
}
⚝ moveTry()
▮▮▮▮⚝ 函数签名:Try<T> moveTry() &&
▮▮▮▮⚝ 描述:与 moveResult()
功能相同,是 moveResult()
的别名,为了更清晰地表达“移动 Try
结果”的意图。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Try<T>
,与 moveResult()
的返回值相同。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Try.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> future1 = folly::makeFuture(515253);
7
folly::Try<int> movedTry1 = future1.moveTry();
8
if (movedTry1.hasValue()) {
9
std::cout << "moveTry() value: " << movedTry1.value() << std::endl; // 输出: moveTry() value: 515253
10
}
11
std::cout << "future1 isReady after moveTry(): " << future1.isReady() << std::endl; // 输出: future1 isReady after moveTry(): 0
12
13
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("MoveTry error"));
14
folly::Try<int> movedTry2 = errorFuture.moveTry();
15
if (movedTry2.hasException()) {
16
try {
17
movedTry2.throwException();
18
} catch (const std::exception& e) {
19
std::cerr << "moveTry() caught error: " << e.what() << std::endl; // 输出: moveTry() caught error: MoveTry error
20
}
21
}
22
std::cout << "errorFuture isReady after moveTry(): " << errorFuture.isReady() << std::endl; // 输出: errorFuture isReady after moveTry(): 0
23
24
return 0;
25
}
⚝ move()
▮▮▮▮⚝ 函数签名:Future<T> move() &&
▮▮▮▮⚝ 描述:移动提取 Future
对象本身。返回一个新的 Future<T>
对象,该对象接管了原始 Future
的状态,并将原始 Future
的状态重置为未完成。move()
只能调用一次,后续调用行为未定义。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Future<T>
,移动后的 Future<T>
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> future1 = folly::makeFuture(545556);
6
folly::Future<int> movedFuture1 = future1.move();
7
std::cout << "movedFuture1 value: " << movedFuture1.value() << std::endl; // 输出: movedFuture1 value: 545556
8
std::cout << "future1 isReady after move(): " << future1.isReady() << std::endl; // 输出: future1 isReady after move(): 0
9
10
folly::Future<int> errorFuture = folly::makeFutureError<int>(std::runtime_error("Move Future error"));
11
folly::Future<int> movedFuture2 = errorFuture.move();
12
movedFuture2.then([](folly::Try<int>&& finalTry) {
13
if (finalTry.hasException()) {
14
try {
15
finalTry.throwException();
16
} catch (const std::exception& e) {
17
std::cerr << "movedFuture2 caught error: " << e.what() << std::endl; // 输出: movedFuture2 caught error: Move Future error
18
}
19
}
20
return folly::Unit();
21
});
22
std::cout << "errorFuture isReady after move(): " << errorFuture.isReady() << std::endl; // 输出: errorFuture isReady after move(): 0
23
24
return 0;
25
}
⑫ 资源管理 (Resource Management)
⚝ release()
▮▮▮▮⚝ 函数签名:void release() &&
▮▮▮▮⚝ 描述:释放 Future
对象持有的资源,并将 Future
的状态重置为未完成。release()
通常用于手动管理 Future
的生命周期,例如在某些特殊内存管理场景下。调用 release()
后,Future
对象将不再有效,后续操作行为未定义。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:void
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> future = folly::makeFuture(575859);
6
std::cout << "future isReady before release(): " << future.isReady() << std::endl; // 输出: future isReady before release(): 1
7
future.release();
8
std::cout << "future isReady after release(): " << future.isReady() << std::endl; // 输出: future isReady after release(): 0
9
// future 对象在 release() 后不再有效,避免继续使用
10
return 0;
11
}
⚝ reset()
▮▮▮▮⚝ 函数签名:void reset()
▮▮▮▮⚝ 描述:将 Future
对象的状态重置为未完成,但不释放其持有的资源。reset()
可以用于重用 Future
对象,例如在循环中重复使用同一个 Future
变量。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:void
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> future = folly::makeFuture(606162);
6
std::cout << "future isReady before reset(): " << future.isReady() << std::endl; // 输出: future isReady before reset(): 1
7
future.reset();
8
std::cout << "future isReady after reset(): " << future.isReady() << std::endl; // 输出: future isReady after reset(): 0
9
// future 对象可以再次使用,例如与 Promise 关联
10
return 0;
11
}
⚝ swap(Future<T>& other)
▮▮▮▮⚝ 函数签名:void swap(Future<T>& other)
▮▮▮▮⚝ 描述:交换当前 Future
对象和另一个 Future
对象 other
的状态。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ other
:另一个 Future<T>&
对象。
▮▮▮▮⚝ 返回值:void
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> future1 = folly::makeFuture(636465);
6
folly::Future<int> future2;
7
8
std::cout << "future1 isReady before swap(): " << future1.isReady() << ", future2 isReady before swap(): " << future2.isReady() << std::endl; // 输出: future1 isReady before swap(): 1, future2 isReady before swap(): 0
9
future1.swap(future2);
10
std::cout << "future1 isReady after swap(): " << future1.isReady() << ", future2 isReady after swap(): " << future2.isReady() << std::endl; // 输出: future1 isReady after swap(): 0, future2 isReady after swap(): 1
11
std::cout << "future2 value after swap(): " << future2.value() << std::endl; // 输出: future2 value after swap(): 636465
12
13
return 0;
14
}
⑬ 隐式类型转换运算符 (Implicit Conversion Operators)
⚝ operator bool()
▮▮▮▮⚝ 函数签名:explicit operator bool() const
▮▮▮▮⚝ 描述:隐式转换为 bool
类型。当 Future
对象在布尔上下文中被使用时,会调用此运算符。如果 Future
已完成,则返回 true
,否则返回 false
。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:bool
,true
如果 Future
已完成,false
否则。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> readyFuture = folly::makeFuture(666768);
6
folly::Future<int> unreadyFuture;
7
8
if (readyFuture) {
9
std::cout << "readyFuture is implicitly true." << std::endl; // 输出: readyFuture is implicitly true.
10
} else {
11
std::cout << "readyFuture is implicitly false." << std::endl;
12
}
13
14
if (unreadyFuture) {
15
std::cout << "unreadyFuture is implicitly true." << std::endl;
16
} else {
17
std::cout << "unreadyFuture is implicitly false." << std::endl; // 输出: unreadyFuture is implicitly false.
18
}
19
20
return 0;
21
}
⚝ operator->()
▮▮▮▮⚝ 函数签名:T* operator->() &&
和 T const* operator->() const&
▮▮▮▮⚝ 描述:指针解引用运算符。仅当 Future<T*>
类型且已完成并持有非空指针时才能使用。返回 Future
持有的指针。如果 Future
未完成、持有异常或空指针,则行为未定义。应谨慎使用,并确保 Future
的状态和指针有效性。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:T*
,Future
持有的指针。
▮▮▮▮⚝ 异常:如果 Future
未完成、持有异常或空指针,则行为未定义。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
struct MyClass {
5
int value;
6
void printValue() const {
7
std::cout << "MyClass value: " << value << std::endl;
8
}
9
};
10
11
int main() {
12
MyClass* ptr = new MyClass{697071};
13
folly::Future<MyClass*> futurePtr = folly::makeFuture(ptr);
14
15
if (futurePtr.hasValue() && futurePtr.value() != nullptr) {
16
futurePtr->printValue(); // 输出: MyClass value: 697071
17
futurePtr->value = 727374;
18
futurePtr->printValue(); // 输出: MyClass value: 727374
19
}
20
21
delete ptr; // 手动释放内存,需要谨慎管理指针生命周期
22
23
return 0;
24
}
⚝ operator*()
▮▮▮▮⚝ 函数签名:T& operator*() &&
和 T const& operator*() const&
▮▮▮▮⚝ 描述:值解引用运算符。仅当 Future<T>
类型且已完成并持有值时才能使用。返回 Future
持有的值的引用。如果 Future
未完成或持有异常,则行为未定义。应谨慎使用,并确保 Future
的状态。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:T&
或 const T&
,Future
持有的值的引用。
▮▮▮▮⚝ 异常:如果 Future
未完成或持有异常,则行为未定义。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> futureValue = folly::makeFuture(757677);
6
7
if (futureValue.hasValue()) {
8
int& valueRef = *futureValue;
9
std::cout << "Dereferenced value: " << valueRef << std::endl; // 输出: Dereferenced value: 757677
10
valueRef = 787980; // 修改解引用后的值
11
std::cout << "Modified dereferenced value: " << *futureValue << std::endl; // 输出: Modified dereferenced value: 787980
12
}
13
14
return 0;
15
}
12.2 Future
相关的自由函数 (Free Functions Related to Future
)
除了 Future
类的方法,folly/futures
库还提供了一系列与 Future
相关的自由函数,用于创建、组合和操作 Future
对象。这些自由函数扩展了 Future
的功能,提供了更灵活的异步编程工具。
① Future 创建函数 (Future Creation Functions)
⚝ makeFuture(T&& value)
, makeFuture(T const& value)
, makeFuture(Unit)
▮▮▮▮⚝ 函数签名:
1
template <typename T>
2
Future<T> makeFuture(T&& value);
3
4
template <typename T>
5
Future<T> makeFuture(T const& value);
6
7
Future<Unit> makeFuture(Unit);
▮▮▮▮⚝ 描述:创建已完成的 Future
对象,并持有指定的值。makeFuture(Unit)
用于创建 Future<folly::Unit>
对象。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ value
:要持有的值,类型为 T
或 folly::Unit
。
▮▮▮▮⚝ 返回值:Future<T>
或 Future<folly::Unit>
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/Unit.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> future1 = folly::makeFuture(818283);
7
std::cout << "makeFuture(value) value: " << future1.value() << std::endl; // 输出: makeFuture(value) value: 818283
8
9
folly::Future<folly::Unit> future2 = folly::makeFuture(folly::Unit());
10
std::cout << "makeFuture(Unit) isReady: " << future2.isReady() << std::endl; // 输出: makeFuture(Unit) isReady: 1
11
12
return 0;
13
}
⚝ makeFutureWith(F&& f)
▮▮▮▮⚝ 函数签名:
1
template <typename F>
2
auto makeFutureWith(F&& f);
▮▮▮▮⚝ 描述:使用函数 f
的返回值创建已完成的 Future
对象。函数 f
同步执行,其返回值会被包装在 Future
中。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:一个函数或函数对象,返回类型为 T
。
▮▮▮▮⚝ 返回值:Future<T>
对象,持有 f()
的返回值。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int syncGetValue() {
5
return 848586;
6
}
7
8
int main() {
9
folly::Future<int> future = folly::makeFutureWith(syncGetValue);
10
std::cout << "makeFutureWith() value: " << future.value() << std::endl; // 输出: makeFutureWith() value: 848586
11
12
return 0;
13
}
⚝ makeFutureDelayed(Duration duration, T&& value)
, makeFutureDelayed(Duration duration, F&& f)
▮▮▮▮⚝ 函数签名:
1
template <typename T>
2
Future<T> makeFutureDelayed(Duration duration, T&& value);
3
4
template <typename T, typename F>
5
Future<T> makeFutureDelayed(Duration duration, F&& f);
▮▮▮▮⚝ 描述:创建在指定延迟后完成的 Future
对象。第一个版本在延迟后持有指定的值 value
完成;第二个版本在延迟后执行函数 f
,并持有 f()
的返回值完成。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ duration
:延迟时长。
▮▮▮▮▮▮▮▮⚝ value
:延迟后要持有的值。
▮▮▮▮▮▮▮▮⚝ f
:延迟后要执行的函数或函数对象,返回类型为 T
。
▮▮▮▮⚝ 返回值:Future<T>
对象,延迟后完成。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <chrono>
4
5
int syncDelayedValue() {
6
std::cout << "syncDelayedValue() executed after delay." << std::endl;
7
return 878889;
8
}
9
10
int main() {
11
folly::Future<int> future1 = folly::makeFutureDelayed(std::chrono::milliseconds(100), 909192);
12
future1.thenValue([](int value) {
13
std::cout << "makeFutureDelayed(value) value: " << value << std::endl; // 输出: makeFutureDelayed(value) value: 909192 (延迟后输出)
14
return folly::Unit();
15
});
16
17
folly::Future<int> future2 = folly::makeFutureDelayed(std::chrono::milliseconds(200), syncDelayedValue);
18
future2.thenValue([](int value) {
19
std::cout << "makeFutureDelayed(f) value: " << value << std::endl; // 输出: syncDelayedValue() executed after delay. (先输出)
20
return folly::Unit(); // 输出: makeFutureDelayed(f) value: 878889 (后输出)
21
});
22
23
return 0;
24
}
⚝ makeFutureTimed(TimePoint tp, T&& value)
, makeFutureTimed(TimePoint tp, F&& f)
▮▮▮▮⚝ 函数签名:
1
template <typename T>
2
Future<T> makeFutureTimed(TimePoint tp, T&& value);
3
4
template <typename T, typename F>
5
Future<T> makeFutureTimed(TimePoint tp, F&& f);
▮▮▮▮⚝ 描述:创建在指定时间点 tp
完成的 Future
对象。与 makeFutureDelayed
类似,但使用时间点而不是时长。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ tp
:完成的时间点。
▮▮▮▮▮▮▮▮⚝ value
:时间点到达后要持有的值。
▮▮▮▮▮▮▮▮⚝ f
:时间点到达后要执行的函数或函数对象,返回类型为 T
。
▮▮▮▮⚝ 返回值:Future<T>
对象,在指定时间点完成.
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <chrono>
4
5
int syncTimedValue() {
6
std::cout << "syncTimedValue() executed at timed point." << std::endl;
7
return 939495;
8
}
9
10
int main() {
11
std::chrono::steady_clock::time_point timedPoint1 = std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
12
folly::Future<int> future1 = folly::makeFutureTimed(timedPoint1, 969798);
13
future1.thenValue([](int value) {
14
std::cout << "makeFutureTimed(value) value: " << value << std::endl; // 输出: makeFutureTimed(value) value: 969798 (在时间点后输出)
15
return folly::Unit();
16
});
17
18
std::chrono::steady_clock::time_point timedPoint2 = std::chrono::steady_clock::now() + std::chrono::milliseconds(200);
19
folly::Future<int> future2 = folly::makeFutureTimed(timedPoint2, syncTimedValue);
20
future2.thenValue([](int value) {
21
std::cout << "makeFutureTimed(f) value: " << value << std::endl; // 输出: syncTimedValue() executed at timed point. (先输出)
22
return folly::Unit(); // 输出: makeFutureTimed(f) value: 939495 (后输出)
23
});
24
25
return 0;
26
}
⚝ makeFutureVoid()
▮▮▮▮⚝ 函数签名:Future<void> makeFutureVoid()
▮▮▮▮⚝ 描述:创建已完成的 Future<void>
对象,表示一个不返回任何值的异步操作已成功完成。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Future<void>
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
void syncVoidTask() {
5
std::cout << "syncVoidTask() executed." << std::endl;
6
}
7
8
int main() {
9
folly::Future<void> future = folly::makeFutureVoid();
10
future.thenValue([](folly::Unit) {
11
std::cout << "makeFutureVoid() completed." << std::endl; // 输出: makeFutureVoid() completed.
12
return folly::Unit();
13
});
14
15
return 0;
16
}
⚝ makeFutureError<T>(exception_ptr)
, makeFutureError<T>(exception_ptr&&)
, makeFutureError<T>(const std::exception&)
, makeFutureError<T>(std::exception&&)
, makeFutureError<T>(const char*)
, makeFutureError<T>(std::string)
▮▮▮▮⚝ 函数签名:提供多种重载版本,接受不同类型的异常信息。
1
template <typename T>
2
Future<T> makeFutureError(exception_ptr ex);
3
4
template <typename T>
5
Future<T> makeFutureError(exception_ptr&& ex);
6
7
template <typename T, typename E>
8
Future<T> makeFutureError(const E& ex);
9
10
template <typename T, typename E>
11
Future<T> makeFutureError(E&& ex);
12
13
template <typename T>
14
Future<T> makeFutureError(const char* msg);
15
16
template <typename T>
17
Future<T> makeFutureError(std::string msg);
▮▮▮▮⚝ 描述:创建已完成的失败 Future
对象,并持有指定的异常。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ ex
:std::exception_ptr
或异常对象,表示错误信息。
▮▮▮▮▮▮▮▮⚝ msg
:错误消息字符串。
▮▮▮▮⚝ 返回值:Future<T>
对象,已完成并持有异常。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <stdexcept>
4
5
int main() {
6
folly::Future<int> future1 = folly::makeFutureError<int>(std::runtime_error("makeFutureError(exception) test"));
7
future1.then([](folly::Try<int>&& finalTry) {
8
if (finalTry.hasException()) {
9
try {
10
finalTry.throwException();
11
} catch (const std::exception& e) {
12
std::cerr << "makeFutureError(exception) caught error: " << e.what() << std::endl; // 输出: makeFutureError(exception) caught error: makeFutureError(exception) test
13
}
14
}
15
return folly::Unit();
16
});
17
18
folly::Future<int> future2 = folly::makeFutureError<int>("makeFutureError(string) test");
19
future2.then([](folly::Try<int>&& finalTry) {
20
if (finalTry.hasException()) {
21
try {
22
finalTry.throwException();
23
} catch (const std::exception& e) {
24
std::cerr << "makeFutureError(string) caught error: " << e.what() << std::endl; // 输出: makeFutureError(string) caught error: makeFutureError(string) test
25
}
26
}
27
return folly::Unit();
28
});
29
30
return 0;
31
}
⚝ makeFutureException<T>(E&& ex)
▮▮▮▮⚝ 函数签名:
1
template <typename T, typename E>
2
Future<T> makeFutureException(E&& ex);
▮▮▮▮⚝ 描述:与 makeFutureError
类似,创建已完成的失败 Future
对象,并持有指定的异常对象 ex
。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ ex
:异常对象,类型为 E
。
▮▮▮▮⚝ 返回值:Future<T>
对象,已完成并持有异常。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <stdexcept>
4
5
int main() {
6
folly::Future<int> future = folly::makeFutureException<int>(std::logic_error("makeFutureException test"));
7
future.then([](folly::Try<int>&& finalTry) {
8
if (finalTry.hasException()) {
9
try {
10
finalTry.throwException();
11
} catch (const std::exception& e) {
12
std::cerr << "makeFutureException caught error: " << e.what() << std::endl; // 输出: makeFutureException caught error: makeFutureException test
13
}
14
}
15
return folly::Unit();
16
});
17
18
return 0;
19
}
⚝ makeFutureCancelled<T>()
▮▮▮▮⚝ 函数签名:Future<T> makeFutureCancelled()
▮▮▮▮⚝ 描述:创建已完成的取消状态 Future
对象。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Future<T>
对象,已完成并被取消。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <folly/exception_wrappers.h>
4
5
int main() {
6
folly::Future<int> future = folly::makeFutureCancelled<int>();
7
future.then([](folly::Try<int>&& finalTry) {
8
if (finalTry.hasException()) {
9
try {
10
finalTry.throwException();
11
} catch (const folly::CancelledException& e) {
12
std::cerr << "makeFutureCancelled caught CancelledException." << std::endl; // 输出: makeFutureCancelled caught CancelledException.
13
} catch (...) {
14
std::cerr << "makeFutureCancelled unexpected exception type." << std::endl;
15
}
16
} else {
17
std::cerr << "makeFutureCancelled unexpected success." << std::endl;
18
}
19
return folly::Unit();
20
});
21
22
return 0;
23
}
⚝ makeFutureMoved<T>()
▮▮▮▮⚝ 函数签名:Future<T> makeFutureMoved()
▮▮▮▮⚝ 描述:创建一个已完成的 moved 状态的 Future
对象。这种状态通常用于表示 Future
的结果已经被移动走,不再持有有效值或异常。
▮▮▮▮⚝ 参数:无
▮▮▮▮⚝ 返回值:Future<T>
对象,已完成并处于 moved 状态。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> future = folly::makeFutureMoved<int>();
6
std::cout << "makeFutureMoved isReady: " << future.isReady() << std::endl; // 输出: makeFutureMoved isReady: 1
7
std::cout << "makeFutureMoved hasValue: " << future.hasValue() << std::endl; // 输出: makeFutureMoved hasValue: 0
8
std::cout << "makeFutureMoved hasException: " << future.hasException() << std::endl; // 输出: makeFutureMoved hasException: 0
9
// 尝试获取 moved Future 的值或异常会导致未定义行为,通常应避免
10
return 0;
11
}
⚝ value(T&& val)
, value(T const& val)
▮▮▮▮⚝ 函数签名:
1
template <typename T>
2
Future<T> value(T&& val);
3
4
template <typename T>
5
Future<T> value(T const& val);
▮▮▮▮⚝ 描述:与 makeFuture
功能相同,是 makeFuture
的别名,为了更简洁地表达“创建值 Future”的意图。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ val
:要持有的值。
▮▮▮▮⚝ 返回值:Future<T>
对象,持有指定的值。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
folly::Future<int> future = folly::futures::value(99100101);
6
std::cout << "value() function result: " << future.value() << std::endl; // 输出: value() function result: 99100101
7
return 0;
8
}
⚝ exception(exception_ptr ex)
, exception(exception_ptr&& ex)
, exception(const std::exception& ex)
, exception(std::exception&& ex)
, exception(const char* msg)
, exception(std::string msg)
▮▮▮▮⚝ 函数签名:与 makeFutureError
类似,提供多种重载版本。
1
template <typename T>
2
Future<T> exception(exception_ptr ex);
3
4
template <typename T>
5
Future<T> exception(exception_ptr&& ex);
6
7
template <typename T, typename E>
8
Future<T> exception(const E& ex);
9
10
template <typename T, typename E>
11
Future<T> exception(E&& ex);
12
13
template <typename T>
14
Future<T> exception(const char* msg);
15
16
template <typename T>
17
Future<T> exception(std::string msg);
▮▮▮▮⚝ 描述:与 makeFutureError
功能相同,是 makeFutureError
的别名,为了更简洁地表达“创建异常 Future”的意图。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ ex
:异常信息。
▮▮▮▮▮▮▮▮⚝ msg
:错误消息字符串。
▮▮▮▮⚝ 返回值:Future<T>
对象,持有指定的异常。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <stdexcept>
4
5
int main() {
6
folly::Future<int> future = folly::futures::exception<int>(std::runtime_error("exception() function test"));
7
future.then([](folly::Try<int>&& finalTry) {
8
if (finalTry.hasException()) {
9
try {
10
finalTry.throwException();
11
} catch (const std::exception& e) {
12
std::cerr << "exception() function caught error: " << e.what() << std::endl; // 输出: exception() function caught error: exception() function test
13
}
14
}
15
return folly::Unit();
16
});
17
18
return 0;
19
}
⚝ error(exception_ptr ex)
, error(exception_ptr&& ex)
, error(const std::exception& ex)
, error(std::exception&& ex)
, error(const char* msg)
, error(std::string msg)
▮▮▮▮⚝ 函数签名:与 makeFutureError
和 exception
类似,提供多种重载版本。
1
template <typename T>
2
Future<T> error(exception_ptr ex);
3
4
template <typename T>
5
Future<T> error(exception_ptr&& ex);
6
7
template <typename T, typename E>
8
Future<T> error(const E& ex);
9
10
template <typename T, typename E>
11
Future<T> error(E&& ex);
12
13
template <typename T>
14
Future<T> error(const char* msg);
15
16
template <typename T>
17
Future<T> error(std::string msg);
▮▮▮▮⚝ 描述:与 makeFutureError
和 exception
功能相同,是它们的别名,为了更简洁地表达“创建错误 Future”的意图。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ ex
:异常信息。
▮▮▮▮▮▮▮▮⚝ msg
:错误消息字符串。
▮▮▮▮⚝ 返回值:Future<T>
对象,持有指定的异常。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <stdexcept>
4
5
int main() {
6
folly::Future<int> future = folly::futures::error<int>(std::runtime_error("error() function test"));
7
future.then([](folly::Try<int>&& finalTry) {
8
if (finalTry.hasException()) {
9
try {
10
finalTry.throwException();
11
} catch (const std::exception& e) {
12
std::cerr << "error() function caught error: " << e.what() << std::endl; // 输出: error() function caught error: error() function test
13
}
14
}
15
return folly::Unit();
16
});
17
18
return 0;
19
}
② Future 组合函数 (Future Combination Functions)
⚝ collect(Futures<T>&& futures)
, collect(Futures<T> const& futures)
▮▮▮▮⚝ 函数签名:
1
template <template <typename...> class Container, typename T>
2
Future<Container<T>> collect(Container<Future<T>>&& futures);
3
4
template <template <typename...> class Container, typename T>
5
Future<Container<T>> collect(Container<Future<T>> const& futures);
▮▮▮▮⚝ 描述:等待多个 Future
对象全部完成。返回一个新的 Future
对象,当所有输入的 Future
都成功完成时,新的 Future
也成功完成,并持有包含所有结果的容器(例如 std::vector
)。如果任何一个输入的 Future
失败,则新的 Future
也会立即失败,并携带第一个失败的 Future
的异常。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ futures
:包含多个 Future<T>
对象的容器,例如 std::vector<Future<T>>
。
▮▮▮▮⚝ 返回值:Future<Container<T>>
对象,持有所有结果的容器或第一个失败的异常。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <vector>
4
5
folly::Future<int> asyncValue(int value, std::chrono::milliseconds delay) {
6
return folly::makeFutureDelayed(delay, value);
7
}
8
9
int main() {
10
std::vector<folly::Future<int>> futures;
11
futures.push_back(asyncValue(1, std::chrono::milliseconds(50)));
12
futures.push_back(asyncValue(2, std::chrono::milliseconds(100)));
13
futures.push_back(asyncValue(3, std::chrono::milliseconds(75)));
14
15
auto collectedFuture = folly::collect(futures);
16
collectedFuture.thenValue([](const std::vector<int>& results) {
17
std::cout << "collect() results: ";
18
for (int result : results) {
19
std::cout << result << " "; // 输出: collect() results: 1 2 3
20
}
21
std::cout << std::endl;
22
return folly::Unit();
23
});
24
25
return 0;
26
}
⚝ collectAll(Futures<T>&& futures)
, collectAll(Futures<T> const& futures)
▮▮▮▮⚝ 函数签名:与 collect
相同。
1
template <template <typename...> class Container, typename T>
2
Future<Container<Try<T>>> collectAll(Container<Future<T>>&& futures);
3
4
template <template <typename...> class Container, typename T>
5
Future<Container<Try<T>>> collectAll(Container<Future<T>> const& futures);
▮▮▮▮⚝ 描述:与 collect
类似,等待多个 Future
对象全部完成。但 collectAll
无论输入 Future
成功或失败,都会等待所有 Future
完成。返回的 Future
成功时,持有包含所有 Try<T>
结果的容器,每个 Try<T>
对象封装了对应 Future
的结果(值或异常)。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ futures
:包含多个 Future<T>
对象的容器。
▮▮▮▮⚝ 返回值:Future<Container<Try<T>>>
对象,持有所有 Try<T>
结果的容器。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <vector>
4
#include <stdexcept>
5
6
folly::Future<int> asyncMaybeFail(int value, std::chrono::milliseconds delay, bool fail) {
7
if (fail) {
8
return folly::makeFutureDelayed<int>(delay, [](){ throw std::runtime_error("Async operation failed"); });
9
} else {
10
return folly::makeFutureDelayed(delay, value);
11
}
12
}
13
14
int main() {
15
std::vector<folly::Future<int>> futures;
16
futures.push_back(asyncMaybeFail(1, std::chrono::milliseconds(50), false));
17
futures.push_back(asyncMaybeFail(2, std::chrono::milliseconds(100), true)); // 模拟一个失败的 Future
18
futures.push_back(asyncMaybeFail(3, std::chrono::milliseconds(75), false));
19
20
auto collectedAllFuture = folly::collectAll(futures);
21
collectedAllFuture.thenValue([](const std::vector<folly::Try<int>>& tryResults) {
22
std::cout << "collectAll() results: ";
23
for (const auto& tryResult : tryResults) {
24
if (tryResult.hasValue()) {
25
std::cout << tryResult.value() << " ";
26
} else {
27
std::cout << "[Error] ";
28
}
29
}
30
std::cout << std::endl; // 输出: collectAll() results: 1 [Error] 3
31
return folly::Unit();
32
});
33
34
return 0;
35
}
⚝ collectAny(Futures<T>&& futures)
, collectAny(Futures<T> const& futures)
▮▮▮▮⚝ 函数签名:
1
template <template <typename...> class Container, typename T>
2
Future<Container<Try<T>>> collectAny(Container<Future<T>>&& futures);
3
4
template <template <typename...> class Container, typename T>
5
Future<Container<Try<T>>> collectAny(Container<Future<T>> const& futures);
▮▮▮▮⚝ 描述:与 collectAll
类似,等待多个 Future
对象全部完成,并收集所有 Try<T>
结果。collectAny
与 collectAll
的区别可能在于错误处理或取消策略,具体行为需要查阅文档或代码实现。通常 collectAny
也用于等待所有 Future 完成,并收集所有结果,但可能在某些边缘情况下与 collectAll
有细微差异。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ futures
:包含多个 Future<T>
对象的容器。
▮▮▮▮⚝ 返回值:Future<Container<Try<T>>>
对象,持有所有 Try<T>
结果的容器。
▮▮▮▮⚝ 示例: (示例与 collectAll
类似,具体差异需参考文档)
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <vector>
4
#include <stdexcept>
5
6
// ... (asyncMaybeFail 函数与 collectAll 示例相同) ...
7
8
int main() {
9
std::vector<folly::Future<int>> futures;
10
futures.push_back(asyncMaybeFail(1, std::chrono::milliseconds(50), false));
11
futures.push_back(asyncMaybeFail(2, std::chrono::milliseconds(100), true));
12
futures.push_back(asyncMaybeFail(3, std::chrono::milliseconds(75), false));
13
14
auto collectedAnyFuture = folly::collectAny(futures);
15
collectedAnyFuture.thenValue([](const std::vector<folly::Try<int>>& tryResults) {
16
std::cout << "collectAny() results: ";
17
for (const auto& tryResult : tryResults) {
18
if (tryResult.hasValue()) {
19
std::cout << tryResult.value() << " ";
20
} else {
21
std::cout << "[Error] ";
22
}
23
}
24
std::cout << std::endl; // 输出: collectAny() results: 1 [Error] 3 (可能与 collectAll 输出相同)
25
return folly::Unit();
26
});
27
28
return 0;
29
}
⚝ select(Futures<T>&& futures)
, select(Futures<T> const& futures)
▮▮▮▮⚝ 函数签名:
1
template <template <typename...> class Container, typename T>
2
Future<Try<T>> select(Container<Future<T>>&& futures);
3
4
template <template <typename...> class Container, typename T>
5
Future<Try<T>> select(Container<Future<T>> const& futures);
▮▮▮▮⚝ 描述:选择第一个完成的 Future
对象。返回一个新的 Future
对象,当输入容器中任何一个 Future
完成时,新的 Future
立即完成,并持有第一个完成的 Future
的 Try<T>
结果。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ futures
:包含多个 Future<T>
对象的容器。
▮▮▮▮⚝ 返回值:Future<Try<T>>
对象,持有第一个完成的 Future
的 Try<T>
结果.
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <vector>
4
5
folly::Future<int> asyncValueWithDelay(int value, std::chrono::milliseconds delay) {
6
return folly::makeFutureDelayed(delay, value);
7
}
8
9
int main() {
10
std::vector<folly::Future<int>> futures;
11
futures.push_back(asyncValueWithDelay(1, std::chrono::milliseconds(100)));
12
futures.push_back(asyncValueWithDelay(2, std::chrono::milliseconds(50))); // 最先完成
13
futures.push_back(asyncValueWithDelay(3, std::chrono::milliseconds(150)));
14
15
auto selectedFuture = folly::select(futures);
16
selectedFuture.thenTry([](folly::Try<int>&& tryResult) {
17
if (tryResult.hasValue()) {
18
std::cout << "select() first result: " << tryResult.value() << std::endl; // 输出: select() first result: 2 (最先完成的 Future 的值)
19
} else {
20
std::cerr << "select() first error." << std::endl;
21
}
22
return folly::Unit();
23
});
24
25
return 0;
26
}
⚝ selectN(Futures<T>&& futures, size_t n)
, selectN(Futures<T> const& futures, size_t n)
▮▮▮▮⚝ 函数签名:
1
template <template <typename...> class Container, typename T>
2
Future<Container<Try<T>>> selectN(Container<Future<T>>&& futures, size_t n);
3
4
template <template <typename...> class Container, typename T>
5
Future<Container<Try<T>>> selectN(Container<Future<T>> const& futures, size_t n);
▮▮▮▮⚝ 描述:选择前 n
个完成的 Future
对象。返回一个新的 Future
对象,当输入容器中前 n
个 Future
完成时,新的 Future
完成,并持有包含这 n
个 Future
的 Try<T>
结果的容器。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ futures
:包含多个 Future<T>
对象的容器。
▮▮▮▮▮▮▮▮⚝ n
:要选择的完成 Future
的数量。
▮▮▮▮⚝ 返回值:Future<Container<Try<T>>>
对象,持有前 n
个完成的 Future
的 Try<T>
结果的容器。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <vector>
4
5
folly::Future<int> asyncValueWithDelayN(int value, std::chrono::milliseconds delay) {
6
return folly::makeFutureDelayed(delay, value);
7
}
8
9
int main() {
10
std::vector<folly::Future<int>> futures;
11
futures.push_back(asyncValueWithDelayN(1, std::chrono::milliseconds(100)));
12
futures.push_back(asyncValueWithDelayN(2, std::chrono::milliseconds(50))); // 第二快完成
13
futures.push_back(asyncValueWithDelayN(3, std::chrono::milliseconds(150)));
14
futures.push_back(asyncValueWithDelayN(4, std::chrono::milliseconds(25))); // 最快完成
15
futures.push_back(asyncValueWithDelayN(5, std::chrono::milliseconds(200)));
16
17
auto selectNFuture = folly::selectN(futures, 2); // 选择前 2 个完成的 Future
18
selectNFuture.thenValue([](const std::vector<folly::Try<int>>& tryResults) {
19
std::cout << "selectN(2) results: ";
20
for (const auto& tryResult : tryResults) {
21
if (tryResult.hasValue()) {
22
std::cout << tryResult.value() << " "; // 输出: selectN(2) results: 4 2 (最先完成的两个 Future 的值,顺序可能不固定)
23
} else {
24
std::cout << "[Error] ";
25
}
26
}
27
std::cout << std::endl;
28
return folly::Unit();
29
});
30
31
return 0;
32
}
⚝ race(Futures<T>&& futures)
, race(Futures<T> const& futures)
▮▮▮▮⚝ 函数签名:
1
template <template <typename...> class Container, typename T>
2
Future<Try<T>> race(Container<Future<T>>&& futures);
3
4
template <template <typename...> class Container, typename T>
5
Future<Try<T>> race(Container<Future<T>> const& futures);
▮▮▮▮⚝ 描述:竞争多个 Future
对象,返回第一个完成的 Future
的结果。与 select
功能类似,但 race
更强调“竞争”的语义。返回一个新的 Future
对象,当输入容器中任何一个 Future
完成时,新的 Future
立即完成,并持有第一个完成的 Future
的 Try<T>
结果。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ futures
:包含多个 Future<T>
对象的容器。
▮▮▮▮⚝ 返回值:Future<Try<T>>
对象,持有第一个完成的 Future
的 Try<T>
结果。
▮▮▮▮⚝ 示例: (示例与 select
类似,语义侧重点不同)
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <vector>
4
5
// ... (asyncValueWithDelay 函数与 select 示例相同) ...
6
7
int main() {
8
std::vector<folly::Future<int>> futures;
9
futures.push_back(asyncValueWithDelay(1, std::chrono::milliseconds(100)));
10
futures.push_back(asyncValueWithDelay(2, std::chrono::milliseconds(50))); // 最先完成
11
futures.push_back(asyncValueWithDelay(3, std::chrono::milliseconds(150)));
12
13
auto raceFuture = folly::race(futures);
14
raceFuture.thenTry([](folly::Try<int>&& tryResult) {
15
if (tryResult.hasValue()) {
16
std::cout << "race() first result: " << tryResult.value() << std::endl; // 输出: race() first result: 2 (最先完成的 Future 的值)
17
} else {
18
std::cerr << "race() first error." << std::endl;
19
}
20
return folly::Unit();
21
});
22
23
return 0;
24
}
⚝ whenAll(Futures<T>&& futures)
, whenAll(Futures<T> const& futures)
▮▮▮▮⚝ 函数签名:与 collect
相同。
1
template <template <typename...> class Container, typename T>
2
Future<Container<T>> whenAll(Container<Future<T>>&& futures);
3
4
template <template <typename...> class Container, typename T>
5
Future<Container<T>> whenAll(Container<Future<T>> const& futures);
▮▮▮▮⚝ 描述:与 collect
功能相同,是 collect
的别名,为了更清晰地表达“当所有...时”的意图。等待多个 Future
对象全部完成,并返回包含所有结果的容器。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ futures
:包含多个 Future<T>
对象的容器。
▮▮▮▮⚝ 返回值:Future<Container<T>>
对象,持有所有结果的容器或第一个失败的异常,与 collect
的返回值相同。
▮▮▮▮⚝ 示例: (示例与 collect
相同,语义侧重点不同)
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <vector>
4
5
// ... (asyncValue 函数与 collect 示例相同) ...
6
7
int main() {
8
std::vector<folly::Future<int>> futures;
9
futures.push_back(asyncValue(1, std::chrono::milliseconds(50)));
10
futures.push_back(asyncValue(2, std::chrono::milliseconds(100)));
11
futures.push_back(asyncValue(3, std::chrono::milliseconds(75)));
12
13
auto whenAllFuture = folly::whenAll(futures);
14
whenAllFuture.thenValue([](const std::vector<int>& results) {
15
std::cout << "whenAll() results: ";
16
for (int result : results) {
17
std::cout << result << " "; // 输出: whenAll() results: 1 2 3
18
}
19
std::cout << std::endl;
20
return folly::Unit();
21
});
22
23
return 0;
24
}
⚝ whenAny(Futures<T>&& futures)
, whenAny(Futures<T> const& futures)
▮▮▮▮⚝ 函数签名:与 select
相同。
1
template <template <typename...> class Container, typename T>
2
Future<Try<T>> whenAny(Container<Future<T>>&& futures);
3
4
template <template <typename...> class Container, typename T>
5
Future<Try<T>> whenAny(Container<Future<T>> const& futures);
▮▮▮▮⚝ 描述:与 select
功能相同,是 select
的别名,为了更清晰地表达“当任何一个...时”的意图。选择第一个完成的 Future
对象,并返回其结果。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ futures
:包含多个 Future<T>
对象的容器。
▮▮▮▮⚝ 返回值:Future<Try<T>>
对象,持有第一个完成的 Future
的 Try<T>
结果,与 select
的返回值相同。
▮▮▮▮⚝ 示例: (示例与 select
相同,语义侧重点不同)
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <vector>
4
5
// ... (asyncValueWithDelay 函数与 select 示例相同) ...
6
7
int main() {
8
std::vector<folly::Future<int>> futures;
9
futures.push_back(asyncValueWithDelay(1, std::chrono::milliseconds(100)));
10
futures.push_back(asyncValueWithDelay(2, std::chrono::milliseconds(50))); // 最先完成
11
futures.push_back(asyncValueWithDelay(3, std::chrono::milliseconds(150)));
12
13
auto whenAnyFuture = folly::whenAny(futures);
14
whenAnyFuture.thenTry([](folly::Try<int>&& tryResult) {
15
if (tryResult.hasValue()) {
16
std::cout << "whenAny() first result: " << tryResult.value() << std::endl; // 输出: whenAny() first result: 2 (最先完成的 Future 的值)
17
} else {
18
std::cerr << "whenAny() first error." << std::endl;
19
}
20
return folly::Unit();
21
});
22
23
return 0;
24
}
③ 执行上下文控制函数 (Execution Context Control Functions)
⚝ via(Executor* executor, Future<T>&& future)
, via(Executor* executor, Future<T> const& future)
▮▮▮▮⚝ 函数签名:
1
template <typename T>
2
Future<T> via(Executor* executor, Future<T>&& future);
3
4
template <typename T>
5
Future<T> via(Executor* executor, Future<T> const& future);
▮▮▮▮⚝ 描述:指定 Future
的后续操作在哪个 Executor
上执行。返回一个新的 Future
对象,其链式操作(例如 then()
, map()
等)会在指定的 Executor
上执行。via()
用于控制异步操作的执行线程或执行环境。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ executor
:folly::Executor
指针,指定执行上下文。
▮▮▮▮▮▮▮▮⚝ future
:要指定执行上下文的 Future<T>
对象。
▮▮▮▮⚝ 返回值:Future<T>
对象,后续操作将在指定 Executor
上执行。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/executors/InlineExecutor.h>
3
#include <iostream>
4
#include <thread>
5
6
folly::Future<int> asyncTaskVia() {
7
std::cout << "asyncTaskVia() executing on thread: " << std::this_thread::get_id() << std::endl;
8
return folly::makeFuture(123);
9
}
10
11
int main() {
12
folly::InlineExecutor inlineExecutor; // 使用内联执行器,在当前线程同步执行
13
folly::Future<int> future = asyncTaskVia();
14
std::cout << "Initial task started on thread: " << std::this_thread::get_id() << std::endl;
15
16
auto viaFuture = folly::via(&inlineExecutor, std::move(future)); // 指定后续操作在 inlineExecutor 上执行
17
viaFuture.thenValue([](int value) {
18
std::cout << "thenValue() callback executing on thread: " << std::this_thread::get_id() << std::endl; // 输出: thenValue() callback executing on thread: ... (与 main 线程相同,因为是 InlineExecutor)
19
std::cout << "via() result value: " << value << std::endl;
20
return folly::Unit();
21
});
22
23
return 0;
24
}
④ 延迟与定时函数 (Delay and Timing Functions)
⚝ delayed(Duration duration)
▮▮▮▮⚝ 函数签名:Future<Unit> delayed(Duration duration)
▮▮▮▮⚝ 描述:创建一个在指定延迟后完成的 Future<folly::Unit>
对象。delayed()
常用于引入延迟或实现定时任务。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ duration
:延迟时长。
▮▮▮▮⚝ 返回值:Future<folly::Unit>
对象,延迟后完成。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <chrono>
4
5
int main() {
6
std::cout << "delayed() starting delay..." << std::endl;
7
folly::Future<folly::Unit> delayFuture = folly::futures::delayed(std::chrono::milliseconds(200));
8
delayFuture.thenValue([](folly::Unit) {
9
std::cout << "delayed() delay completed." << std::endl; // 输出: delayed() delay completed. (200ms 后输出)
10
return folly::Unit();
11
});
12
std::cout << "delayed() initial call finished." << std::endl; // 输出: delayed() initial call finished. (立即输出)
13
14
return 0;
15
}
⚝ timed(TimePoint tp)
▮▮▮▮⚝ 函数签名:Future<Unit> timed(TimePoint tp)
▮▮▮▮⚝ 描述:创建一个在指定时间点 tp
完成的 Future<folly::Unit>
对象。与 delayed
类似,但使用时间点而不是时长。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ tp
:完成的时间点。
▮▮▮▮⚝ 返回值:Future<folly::Unit>
对象,在指定时间点完成。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <chrono>
4
5
int main() {
6
std::cout << "timed() starting timed delay..." << std::endl;
7
std::chrono::steady_clock::time_point timedPoint = std::chrono::steady_clock::now() + std::chrono::milliseconds(200);
8
folly::Future<folly::Unit> timedFuture = folly::futures::timed(timedPoint);
9
timedFuture.thenValue([](folly::Unit) {
10
std::cout << "timed() timed delay completed." << std::endl; // 输出: timed() timed delay completed. (在时间点后输出)
11
return folly::Unit();
12
});
13
std::cout << "timed() initial call finished." << std::endl; // 输出: timed() initial call finished. (立即输出)
14
15
return 0;
16
}
⚝ sleep(double seconds)
▮▮▮▮⚝ 函数签名:Future<Unit> sleep(double seconds)
▮▮▮▮⚝ 描述:创建一个在指定秒数后完成的 Future<folly::Unit>
对象。sleep()
是一个更方便的延迟函数,使用 double
类型表示秒数。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ seconds
:延迟秒数,double
类型。
▮▮▮▮⚝ 返回值:Future<folly::Unit>
对象,延迟后完成。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
std::cout << "sleep() starting sleep for 0.1 seconds..." << std::endl;
6
folly::Future<folly::Unit> sleepFuture = folly::futures::sleep(0.1); // 延迟 0.1 秒
7
sleepFuture.thenValue([](folly::Unit) {
8
std::cout << "sleep() sleep completed." << std::endl; // 输出: sleep() sleep completed. (0.1 秒后输出)
9
return folly::Unit();
10
});
11
std::cout << "sleep() initial call finished." << std::endl; // 输出: sleep() initial call finished. (立即输出)
12
13
return 0;
14
}
⚝ usleep(int64_t microseconds)
▮▮▮▮⚝ 函数签名:Future<Unit> usleep(int64_t microseconds)
▮▮▮▮⚝ 描述:创建一个在指定微秒数后完成的 Future<folly::Unit>
对象。usleep()
提供微秒级别的延迟控制。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ microseconds
:延迟微秒数,int64_t
类型。
▮▮▮▮⚝ 返回值:Future<folly::Unit>
对象,延迟后完成。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
4
int main() {
5
std::cout << "usleep() starting usleep for 100000 microseconds (0.1 seconds)..." << std::endl;
6
folly::Future<folly::Unit> usleepFuture = folly::futures::usleep(100000); // 延迟 100000 微秒 = 0.1 秒
7
usleepFuture.thenValue([](folly::Unit) {
8
std::cout << "usleep() usleep completed." << std::endl; // 输出: usleep() usleep completed. (0.1 秒后输出)
9
return folly::Unit();
10
});
11
std::cout << "usleep() initial call finished." << std::endl; // 输出: usleep() initial call finished. (立即输出)
12
13
return 0;
14
}
⑤ 与 SemiFuture
转换函数 (Conversion with SemiFuture
)
⚝ toSemiFuture(Future<T> const& f)
▮▮▮▮⚝ 函数签名:SemiFuture<T> toSemiFuture(Future<T> const& f)
▮▮▮▮⚝ 描述:将 Future<T>
转换为 SemiFuture<T>
。与 Future::semi()
方法类似,但 toSemiFuture
是一个自由函数,接受 Future
对象作为参数。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:要转换的 Future<T>
对象。
▮▮▮▮⚝ 返回值:SemiFuture<T>
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/futures/SemiFuture.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<int> future = folly::makeFuture(102103104);
7
folly::SemiFuture<int> semiFuture = folly::futures::toSemiFuture(future);
8
9
semiFuture.thenValue([](int value) {
10
std::cout << "toSemiFuture() SemiFuture value: " << value << std::endl; // 输出: toSemiFuture() SemiFuture value: 102103104
11
return folly::Unit();
12
});
13
14
return 0;
15
}
⚝ toFuture(SemiFuture<T> const& sf)
▮▮▮▮⚝ 函数签名:Future<T> toFuture(SemiFuture<T> const& sf)
▮▮▮▮⚝ 描述:将 SemiFuture<T>
转换为 Future<T>
。与 Future
的构造函数接受 SemiFuture
参数类似,toFuture
是一个自由函数,用于执行转换。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ sf
:要转换的 SemiFuture<T>
对象。
▮▮▮▮⚝ 返回值:Future<T>
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/futures/SemiFuture.h>
3
#include <iostream>
4
5
int main() {
6
folly::Promise<int> promise;
7
folly::SemiFuture<int> semiFuture = promise.getSemiFuture();
8
folly::Future<int> future = folly::futures::toFuture(semiFuture);
9
promise.setValue(105106107);
10
11
future.thenValue([](int value) {
12
std::cout << "toFuture() Future value: " << value << std::endl; // 输出: toFuture() Future value: 105106107
13
return folly::Unit();
14
});
15
16
return 0;
17
}
⑥ 移动语义辅助函数 (Move Semantics Helper Functions)
⚝ futureMove(Future<T>&& f)
, futureMove(SemiFuture<T>&& sf)
▮▮▮▮⚝ 函数签名:
1
template <typename T>
2
Future<T> futureMove(Future<T>&& f);
3
4
template <typename T>
5
Future<T> futureMove(SemiFuture<T>&& sf);
▮▮▮▮⚝ 描述:强制将 Future
或 SemiFuture
对象移动到新的 Future
对象中。在某些情况下,编译器可能无法自动推导出移动语义,futureMove
可以显式地强制移动,提高性能。
▮▮▮▮⚝ 参数:
▮▮▮▮▮▮▮▮⚝ f
:要移动的 Future<T>&&
对象。
▮▮▮▮▮▮▮▮⚝ sf
:要移动的 SemiFuture<T>&&
对象。
▮▮▮▮⚝ 返回值:Future<T>
对象,移动后的 Future
对象。
▮▮▮▮⚝ 示例:
1
#include <folly/futures/Future.h>
2
#include <folly/futures/SemiFuture.h>
3
#include <iostream>
4
5
int main() {
6
folly::Future<std::string> originalFuture = folly::makeFuture("Original String");
7
folly::Future<std::string> movedFuture1 = folly::futures::futureMove(std::move(originalFuture)); // 显式移动 Future
8
std::cout << "futureMove(Future) value: " << movedFuture1.value() << std::endl; // 输出: futureMove(Future) value: Original String
9
10
folly::Promise<std::string> promise;
11
folly::SemiFuture<std::string> semiFuture = promise.getSemiFuture();
12
folly::Future<std::string> movedFuture2 = folly::futures::futureMove(std::move(semiFuture)); // 显式移动 SemiFuture
13
promise.setValue("SemiFuture String");
14
std::cout << "futureMove(SemiFuture) value: " << movedFuture2.value() << std::endl; // 输出: futureMove(SemiFuture) value: SemiFuture String
15
16
return 0;
17
}
⑦ 协程支持 (Coroutine Support)
⚝ co_await(Future<T>&& future)
, co_await(SemiFuture<T>&& semiFuture)
(C++20 协程支持,具体用法和签名可能因编译器和库版本而异)
▮▮▮▮⚝ 描述:co_await
关键字用于在 C++20 协程中等待 Future
或 SemiFuture
完成。co_await
允许在协程中以同步的方式编写异步代码,提高代码的可读性和可维护性。具体用法和签名需要参考 C++20 协程和 folly/futures
库的文档。
▮▮▮▮⚝ 示例: (需要 C++20 协程支持)
1
#include <folly/futures/Future.h>
2
#include <iostream>
3
#include <coroutine>
4
5
folly::Future<int> asyncCoroutineTask() {
6
return folly::makeFutureDelayed(std::chrono::milliseconds(100), 108109110);
7
}
8
9
folly::Future<void> exampleCoroutine() {
10
co_await folly::futures::delayed(std::chrono::milliseconds(50)); // 异步等待延迟
11
int result = co_await asyncCoroutineTask(); // 异步等待 Future 结果
12
std::cout << "co_await result: " << result << std::endl; // 输出: co_await result: 108109110
13
}
14
15
int main() {
16
exampleCoroutine().wait(); // 启动并等待协程完成
17
return 0;
18
}
本章详细解析了 folly::Future
类的常用方法和相关的自由函数,涵盖了 Future
的创建、状态检查、结果访问、链式操作、错误处理、取消与超时控制、组合操作、执行上下文控制、延迟与定时、类型转换、资源管理以及协程支持等各个方面。通过深入理解这些 API,读者可以更加灵活和高效地使用 folly/futures
库进行异步编程,构建高性能、高并发的应用程序。
END_OF_CHAPTER
13. chapter 13: Promise
API 全面解析 (Comprehensive API Analysis of Promise
)
13.1 Promise
类的方法详解 (Detailed Explanation of Promise
Class Methods)
folly::Promise<T>
是 folly/futures
库中用于管理 Future<T>
的核心类之一。它充当了设置 Future
结果的入口点,允许在异步操作完成时设置 Future
的值、异常或取消状态。本节将深入探讨 Promise
类的各种方法,并通过代码示例详细解释其用法和功能,帮助读者全面掌握 Promise
API 的使用。
Promise<T>
类的主要作用可以概括为:
① 创建 Future
: Promise
对象是创建 Future
对象的源头。每个 Promise
对象都关联着一个 Future
对象,可以通过 Promise
的方法来设置这个关联 Future
的最终结果。
② 设置 Future
的结果: Promise
提供了多种方法来设置其关联 Future
的结果,包括成功值、异常或取消状态。一旦 Promise
的结果被设置,与之关联的 Future
对象的状态也会随之改变,并通知所有等待该 Future
的回调。
③ 单次设置: Promise
的结果只能被设置一次。一旦值、异常或取消状态被设置,后续的设置操作将被忽略或抛出异常(具体行为取决于方法)。这确保了 Future
结果的唯一性和不可变性。
④ 线程安全: Promise
的方法设计为线程安全的,可以在不同的线程中安全地设置 Promise
的结果,从而实现跨线程的异步操作结果传递。
接下来,我们将详细介绍 Promise<T>
类提供的各种方法。
1. 构造函数 (Constructors)
Promise<T>
类提供了多种构造函数,用于创建 Promise
对象。
⚝ 默认构造函数 (Default Constructor)
1
Promise();
1
⚝ 默认构造函数创建一个新的 `Promise` 对象。初始状态下,该 `Promise` 既没有值也没有异常,其关联的 `Future` 处于未完成(unready)状态。
1
#include <folly/futures/Promise.h>
2
#include <iostream>
3
4
int main() {
5
folly::Promise<int> promise;
6
folly::Future<int> future = promise.getFuture();
7
8
std::cout << "Future is ready: " << future.isReady() << std::endl; // 输出: Future is ready: 0 (false)
9
10
return 0;
11
}
⚝ 移动构造函数 (Move Constructor)
1
`Promise` 类支持移动构造,但通常情况下,直接构造即可,移动构造在特定高级场景下可能有用,但对于日常使用并不常见,此处暂不详细展开,感兴趣的读者可以查阅相关 C++ 移动语义的资料。
2. getFuture()
方法
1
Future<T> getFuture();
⚝ getFuture()
方法用于获取与当前 Promise
对象关联的 Future<T>
对象。每个 Promise
对象只能调用一次 getFuture()
方法。多次调用同一个 Promise
对象的 getFuture()
方法是未定义行为,通常会导致程序崩溃或不可预测的结果。
⚝ Future
对象是只读的,用于获取异步操作的结果。Promise
对象是可写的,用于设置异步操作的结果。Promise
和 Future
通过 getFuture()
方法关联起来,形成异步操作的完整生命周期。
1
#include <folly/futures/Promise.h>
2
#include <iostream>
3
4
int main() {
5
folly::Promise<std::string> promise;
6
folly::Future<std::string> future = promise.getFuture();
7
8
// ... 异步操作 ...
9
promise.setValue("Hello, Future!"); // 在异步操作完成后设置 Promise 的值
10
11
future.thenValue([](const std::string& result) {
12
std::cout << "Future result: " << result << std::endl; // 输出: Future result: Hello, Future!
13
});
14
15
return 0;
16
}
3. 设置结果的方法 (Setting Result Methods)
Promise
类提供了一系列方法来设置其关联 Future
的结果,包括设置值、设置异常和设置取消状态。
⚝ setValue(T&& value)
和 setValue(const T& value)
方法
1
void setValue(T&& value);
2
void setValue(const T& value);
1
⚝ `setValue()` 方法用于设置 `Promise` 的成功值。一旦调用 `setValue()`,关联的 `Future` 将变为已完成(ready)状态,并且持有指定的值。
2
3
⚝ `setValue(T&& value)` 接受右值引用,用于移动语义,避免不必要的拷贝,提高效率。`setValue(const T& value)` 接受常量左值引用,用于拷贝值。
4
5
⚝ **重要**: `setValue()` 只能被调用一次。如果 `Promise` 的值已经被设置(无论是通过 `setValue`、`setException` 还是 `setCancelled`),再次调用 `setValue()` 将会导致未定义行为,通常会抛出异常。
1
#include <folly/futures/Promise.h>
2
#include <iostream>
3
4
int main() {
5
folly::Promise<int> promise;
6
folly::Future<int> future = promise.getFuture();
7
8
promise.setValue(42); // 设置 Promise 的值为 42
9
10
future.thenValue([](int result) {
11
std::cout << "Future value: " << result << std::endl; // 输出: Future value: 42
12
});
13
14
return 0;
15
}
⚝ setException(exception_ptr ex)
和 setException(std::exception_ptr ex)
方法
1
void setException(exception_ptr ex);
2
void setException(std::exception_ptr ex);
1
⚝ `setException()` 方法用于设置 `Promise` 的异常。当异步操作发生错误时,应该调用 `setException()` 来设置异常,而不是 `setValue()`。关联的 `Future` 将变为已完成(ready)状态,并且持有指定的异常。
2
3
⚝ `exception_ptr` 是 C++ 标准库中用于传递异常的类型,通常通过 `std::make_exception_ptr` 创建。
4
5
⚝ **重要**: `setException()` 只能被调用一次。如果 `Promise` 的结果已经被设置,再次调用 `setException()` 将导致未定义行为。
1
#include <folly/futures/Promise.h>
2
#include <stdexcept>
3
#include <iostream>
4
5
int main() {
6
folly::Promise<int> promise;
7
folly::Future<int> future = promise.getFuture();
8
9
promise.setException(std::make_exception_ptr(std::runtime_error("Something went wrong!"))); // 设置 Promise 的异常
10
11
future.thenValue([](int result) {
12
std::cout << "Future value: " << result << std::endl; // 不会被执行
13
}).thenError([](const std::runtime_error& e) {
14
std::cerr << "Future exception: " << e.what() << std::endl; // 输出: Future exception: Something went wrong!
15
});
16
17
return 0;
18
}
⚝ setWith(Try<T>&& result)
和 setWith(const Try<T>& result)
方法
1
void setWith(Try<T>&& result);
2
void setWith(const Try<T>& result);
1
⚝ `setWith()` 方法提供了一种更通用的方式来设置 `Promise` 的结果,它接受一个 `folly::Try<T>` 对象作为参数。`Try<T>` 可以表示一个成功的值或者一个异常。
2
3
⚝ `Try<T>` 是 `folly` 库中用于表示可能成功或失败的结果的类,类似于 `std::expected` 或 `std::variant<T, std::exception_ptr>` 的概念。使用 `Try<T>` 可以更清晰地表达异步操作的结果,并方便地处理成功和失败两种情况。
4
5
⚝ `setWith(Try<T>&& result)` 接受右值引用,用于移动语义。`setWith(const Try<T>& result)` 接受常量左值引用,用于拷贝 `Try` 对象。
6
7
⚝ **重要**: `setWith()` 只能被调用一次。如果 `Promise` 的结果已经被设置,再次调用 `setWith()` 将导致未定义行为。
1
#include <folly/futures/Promise.h>
2
#include <folly/Try.h>
3
#include <stdexcept>
4
#include <iostream>
5
6
int main() {
7
folly::Promise<int> promise;
8
folly::Future<int> future = promise.getFuture();
9
10
folly::Try<int> successResult = 42;
11
folly::Try<int> errorResult = folly::make_exception_ptr<std::runtime_error>("Try failed!");
12
13
promise.setWith(successResult); // 设置 Promise 的结果为成功值
14
15
future.thenTry([](folly::Try<int> result) {
16
if (result.hasValue()) {
17
std::cout << "Future Try value: " << result.value() << std::endl; // 输出: Future Try value: 42
18
} else {
19
std::cerr << "Future Try exception: " << result.exception().what() << std::endl;
20
}
21
});
22
23
folly::Promise<int> promise2;
24
folly::Future<int> future2 = promise2.getFuture();
25
promise2.setWith(errorResult); // 设置 Promise 的结果为异常
26
27
future2.thenTry([](folly::Try<int> result) {
28
if (result.hasValue()) {
29
std::cout << "Future Try value: " << result.value() << std::endl;
30
} else {
31
std::cerr << "Future Try exception: " << result.exception().what() << std::endl; // 输出: Future Try exception: Try failed!
32
}
33
});
34
35
36
return 0;
37
}
⚝ setCancelled()
方法
1
void setCancelled();
1
⚝ `setCancelled()` 方法用于设置 `Promise` 为取消状态。当异步操作被取消时,应该调用 `setCancelled()`。关联的 `Future` 将变为已完成(ready)状态,并且状态为取消。
2
3
⚝ **重要**: `setCancelled()` 只能被调用一次。如果 `Promise` 的结果已经被设置,再次调用 `setCancelled()` 将导致未定义行为。
1
#include <folly/futures/Promise.h>
2
#include <iostream>
3
4
int main() {
5
folly::Promise<int> promise;
6
folly::Future<int> future = promise.getFuture();
7
8
promise.setCancelled(); // 设置 Promise 为取消状态
9
10
future.thenValue([](int result) {
11
std::cout << "Future value: " << result << std::endl; // 不会被执行
12
}).thenError([](const folly::exception_wrapper& ew) {
13
if (ew.is_cancelled()) {
14
std::cout << "Future is cancelled." << std::endl; // 输出: Future is cancelled.
15
} else {
16
std::cerr << "Future exception: " << ew.what() << std::endl;
17
}
18
});
19
20
return 0;
21
}
4. 状态查询方法 (Status Query Methods)
Promise
类本身不直接提供查询状态的方法,状态查询通常通过关联的 Future
对象进行。例如,可以使用 Future::isReady()
、Future::isCancelled()
、Future::hasValue()
和 Future::hasException()
等方法来检查 Future
的状态。由于 Promise
和 Future
紧密关联,通过查询 Future
的状态,可以间接了解 Promise
的状态。
5. Promise
的生命周期管理 (Lifecycle Management of Promise)
⚝ Promise
对象的生命周期通常由其作用域决定。当 Promise
对象超出作用域时,会自动销毁。
⚝ 一旦 Promise
的结果被设置(通过 setValue
、setException
或 setCancelled
),Promise
的使命就完成了。后续对 Promise
对象的操作(除了销毁)通常是不必要的。
⚝ 需要注意的是,即使 Promise
对象被销毁,与其关联的 Future
对象仍然可以继续存在,直到其结果被消费或被垃圾回收(如果适用)。Future
的生命周期不依赖于 Promise
的生命周期,而是依赖于异步操作的结果是否被处理。
总结
folly::Promise<T>
类是 folly/futures
库中至关重要的组成部分,它提供了设置 Future
结果的核心机制。通过 setValue()
、setException()
、setWith()
和 setCancelled()
等方法,可以灵活地控制 Future
的最终状态,从而实现异步操作的结果传递和错误处理。理解和熟练掌握 Promise
API 对于编写高效、可靠的异步程序至关重要。在实际应用中,Promise
通常与异步操作的执行体紧密结合,负责在异步操作完成时通知 Future
,并传递结果或异常信息。
END_OF_CHAPTER
14. chapter 14: 总结与展望 (Summary and Future Outlook)
14.1 folly/futures
的优势与局限性 (Advantages and Limitations of folly/futures
)
folly/futures
作为 Facebook folly
库中的核心组件,为 C++ 异步编程提供了一套强大而高效的工具。它在设计上借鉴了现代异步编程的最佳实践,并在实际应用中经历了大规模、高并发场景的考验。然而,如同任何技术一样,folly/futures
也并非完美无缺,它既有显著的优势,也存在一些局限性。理解这些优势与局限性,有助于我们更合理地选择和使用 folly/futures
,充分发挥其潜力,并规避潜在的风险。
优势 (Advantages):
① 高性能 (High Performance):folly/futures
在设计之初就将性能放在首位。它采用了轻量级的 Future 和 Promise 实现,避免了不必要的开销。通过高效的调度器 (Executor
) 和优化的回调机制,folly/futures
能够最大限度地减少线程切换和上下文切换的成本,从而实现卓越的异步操作性能。尤其在处理高并发、低延迟的场景下,folly/futures
的性能优势尤为突出。
② 丰富的功能 (Rich Features):folly/futures
提供了全面的异步编程功能,远不止简单的 Future 和 Promise。它支持:
▮▮▮▮ⓑ 链式操作 (Chaining Operations):通过 then()
、map()
、flatMap()
等方法,可以优雅地组织复杂的异步流程,将多个异步操作串联起来,形成清晰的异步处理管道。
▮▮▮▮ⓒ 组合操作 (Combination Operations):collect()
、select()
、race()
等方法允许将多个 Future 组合成更复杂的异步操作,例如等待多个 Future 完成、选择最先完成的 Future 等,满足各种并发控制需求。
▮▮▮▮ⓓ 取消 (Cancellation):folly/futures
提供了完善的取消机制,允许在异步操作执行过程中取消未完成的任务,有效地管理资源和避免浪费。
▮▮▮▮ⓔ 超时 (Timeout):通过 within()
方法,可以为 Future 设置超时时间,防止异步操作无限期地等待,提高系统的健壮性。
▮▮▮▮ⓕ 异常处理 (Exception Handling):folly/futures
提供了强大的异常处理机制,通过 catch()
、recover()
等方法,可以优雅地捕获和处理异步操作中发生的异常,保证程序的稳定性和可靠性。
③ 与 folly
生态系统的深度集成 (Deep Integration with folly
Ecosystem):folly/futures
是 folly
库的一部分,与 folly
库的其他组件(如 folly::Executor
、folly::EventBase
、folly::IOThreadPoolExecutor
等)无缝集成。这种深度集成使得 folly/futures
能够充分利用 folly
库提供的各种基础设施和工具,构建更强大、更高效的异步应用。例如,可以使用 folly::Executor
来灵活地控制 Future 的执行线程,使用 folly::EventBase
来集成事件驱动的 I/O 操作。
④ 强大的类型系统 (Strong Type System):folly/futures
充分利用 C++ 模板的优势,提供了强类型的 Future 和 Promise (Future<T>
和 Promise<T>
)。类型系统在编译时就能检查类型错误,避免运行时类型不匹配的问题,提高了代码的健壮性和可维护性。同时,类型系统也为编译器优化提供了更多信息,有助于生成更高效的代码。
⑤ 成熟稳定 (Mature and Stable):folly/futures
在 Facebook 内部经过了多年的大规模应用和持续迭代,经历了各种复杂场景的考验,已经变得非常成熟和稳定。它拥有完善的测试和文档,社区活跃,遇到问题可以及时得到解决。这使得开发者可以放心地在生产环境中使用 folly/futures
,而不用担心遇到难以解决的 bug 或稳定性问题。
局限性 (Limitations):
① 学习曲线 (Learning Curve):虽然 folly/futures
提供了强大的功能,但其概念和 API 相对复杂,学习曲线较为陡峭。初学者可能需要花费一定的时间和精力才能理解 Future、Promise、Executor 等核心概念,并熟练掌握各种操作方法。特别是对于没有异步编程经验的开发者来说,理解异步编程的思维模式本身就是一个挑战。
② 对 folly
库的依赖 (Dependency on folly
Library):folly/futures
是 folly
库的一部分,使用 folly/futures
就意味着需要引入整个 folly
库。folly
库本身是一个庞大而复杂的库,编译和部署都相对繁琐。对于一些只需要简单异步功能的项目来说,引入整个 folly
库可能显得过于重量级。
③ 潜在的误用风险 (Potential for Misuse):folly/futures
的强大功能也意味着更高的误用风险。如果不深入理解其背后的原理和最佳实践,开发者可能会不小心写出低效、甚至有 bug 的异步代码。例如,不恰当的线程调度、不正确的异常处理、不合理的取消操作等都可能导致各种问题。因此,使用 folly/futures
需要开发者具备扎实的异步编程基础和对 folly/futures
深入的理解。
④ 与标准 C++ 异步机制的差异 (Differences from Standard C++ Asynchronous Mechanisms):虽然 C++20 引入了协程 (Coroutines) 和 std::future
等标准异步机制,但 folly/futures
在设计理念和 API 风格上与标准库存在一些差异。例如,folly/futures
更加强调链式操作和组合操作,而标准库的 std::future
则相对简单。这种差异可能会导致开发者在混合使用 folly/futures
和标准库异步机制时感到困惑。
⑤ 社区活跃度相对较低 (Relatively Lower Community Activity Compared to Standard Library): 相比于标准 C++ 库,folly
库的社区活跃度相对较低。虽然 folly
在 Facebook 内部被广泛使用,但在开源社区的普及程度不如标准库。这意味着在遇到问题时,可能更难在社区中找到现成的解决方案,需要更多地依赖官方文档和源码。
总而言之,folly/futures
是一套功能强大、性能卓越的 C++ 异步编程库,尤其适用于构建高性能、高并发的网络服务和应用程序。然而,其学习曲线较陡峭,对 folly
库有依赖,并且存在一定的误用风险。开发者在选择使用 folly/futures
时,需要充分权衡其优势与局限性,并根据具体的项目需求和团队技术水平做出合理的决策。
14.2 异步编程的未来发展趋势 (Future Development Trends of Asynchronous Programming)
异步编程作为解决并发和提高系统性能的关键技术,在软件开发领域的重要性日益凸显。随着硬件技术的不断发展和应用场景的日益复杂,异步编程也在不断演进和发展。展望未来,异步编程将呈现出以下几个重要的发展趋势:
① 语言级别的异步支持将更加普及 (More Widespread Language-Level Asynchronous Support):现代编程语言越来越重视异步编程,并纷纷提供语言级别的支持。例如,C++20 引入了协程 (Coroutines),Rust 提供了 async/await
语法,JavaScript 也有 Promise 和 async/await。语言级别的异步支持能够大大简化异步编程的复杂性,提高开发效率和代码可读性。未来,我们可以预见到更多的编程语言将加入到提供原生异步支持的行列,使得异步编程更加普及和易用。
② 异步编程模型将更加多样化和融合 (More Diverse and Integrated Asynchronous Programming Models):除了 Future/Promise 和协程之外,还存在其他异步编程模型,例如 Actor 模型、CSP (Communicating Sequential Processes) 模型、Fiber (纤程) 等。未来,这些不同的异步编程模型将不再是孤立存在的,而是会相互借鉴、融合,形成更加丰富和灵活的异步编程生态系统。例如,可以将协程与 Actor 模型结合,利用协程的轻量级和易用性,以及 Actor 模型的并发安全性和容错性,构建更加强大的并发应用。
③ 异步编程的工具链将更加完善 (More Complete Tooling for Asynchronous Programming):异步编程的调试和监控一直是一个挑战。传统的同步调试方法在异步环境中往往失效,难以追踪异步操作的执行流程和状态。未来,异步编程的工具链将更加完善,包括:
▮▮▮▮ⓑ 更强大的调试器 (More Powerful Debuggers):能够理解异步代码的执行流程,支持断点调试、单步执行、变量查看等功能,帮助开发者更方便地调试异步程序。
▮▮▮▮ⓒ 更完善的监控和追踪系统 (More Comprehensive Monitoring and Tracing Systems):能够实时监控异步程序的性能指标,例如延迟、吞吐量、错误率等,并提供分布式追踪功能,帮助开发者定位性能瓶颈和错误根源。
▮▮▮▮ⓓ 更智能的静态分析工具 (More Intelligent Static Analysis Tools):能够静态分析异步代码,检测潜在的并发错误、资源泄漏、死锁等问题,提高代码质量和可靠性。
④ 异步编程的应用场景将更加广泛 (Wider Application Scenarios for Asynchronous Programming):异步编程最初主要应用于网络编程和 I/O 密集型场景。随着云计算、大数据、人工智能等技术的快速发展,异步编程的应用场景将更加广泛。例如:
▮▮▮▮ⓑ 微服务架构 (Microservice Architecture):微服务架构强调服务的独立部署和弹性伸缩,异步通信是微服务之间高效协作的关键。异步编程可以帮助构建高性能、低延迟的微服务系统。
▮▮▮▮ⓒ 实时数据处理 (Real-time Data Processing):实时数据处理系统需要快速响应和处理海量数据流,异步编程可以提高数据处理的并发性和吞吐量。
▮▮▮▮ⓓ 人工智能 (Artificial Intelligence):人工智能应用,例如深度学习、自然语言处理等,通常需要处理大规模的数据和复杂的计算任务,异步编程可以加速模型训练和推理过程。
▮▮▮▮ⓔ 物联网 (Internet of Things):物联网设备数量庞大,网络环境复杂,异步通信是物联网设备之间可靠通信的基础。异步编程可以帮助构建可扩展、低功耗的物联网系统。
⑤ 异步编程的性能优化将持续深入 (Continued Performance Optimization of Asynchronous Programming):虽然异步编程本身就具有性能优势,但随着应用场景的日益复杂和性能要求的不断提高,异步编程的性能优化将持续深入。未来的性能优化方向可能包括:
▮▮▮▮ⓑ 更高效的调度器 (More Efficient Schedulers):设计更智能、更高效的调度器,减少线程切换和上下文切换的开销,提高异步任务的执行效率。
▮▮▮▮ⓒ 零拷贝技术 (Zero-Copy Techniques):在异步 I/O 操作中,尽可能地减少数据拷贝,提高数据传输效率。
▮▮▮▮ⓓ 硬件加速 (Hardware Acceleration):利用硬件加速技术,例如 GPU、FPGA 等,加速异步任务的执行,提高整体性能。
总而言之,异步编程正处于快速发展和变革的时期。语言级别的支持、模型的多样化融合、工具链的完善、应用场景的拓展以及性能的持续优化,都预示着异步编程将在未来的软件开发中扮演越来越重要的角色。掌握异步编程技术,理解其发展趋势,将有助于开发者更好地应对未来的技术挑战,构建更高效、更可靠、更强大的软件系统。
END_OF_CHAPTER