Alamofire源码导读二:发起请求及内部加锁的逻辑
以创建一个 DataRequest 为例子

发起请求
创建 SessionManager
顺带也创建了一个 SessionDelegate
持有一个urlSession,持有一个串行的 DispatchQueue A。
注意,这个不是urlSession 回调方法执行时所在的OperationQueue
创建 Requestable 的 struct,并创建underlying 的 URLSessionDataTask
目前不太清楚作用是什么,但是文档上的注释写着 Helper Types。
持有一个 urlRequest。
然后使用这个 Requestable,创建一个 URLSessionDataTask
注意要在SessionManager持有的串行队列中同步创建
sessionManager 创建一个 Request 对象
通过传入参数 URLSessionDataTask 和 urlSession。
Request 会持有传入的 urlSession,并根据URLSessionDataTask,创建一个 TaskDelegate。
外部对这个TaskDelegate 的读取,被锁保护起来了。
/// The delegate for the underlying task.
open internal(set) var delegate: TaskDelegate {
get {
taskDelegateLock.lock() ; defer { taskDelegateLock.unlock() }
return taskDelegate
}
set {
taskDelegateLock.lock() ; defer { taskDelegateLock.unlock() }
taskDelegate = newValue
}
}
创建 TaskDelegate
新创建的 TaskDelegate 会持有传入的URLSessionDataTask.
在初始化方法中,会创建一个最大并发数是1的OperationQueue,并使之处于 suspend 状态。
sessionManger 持有 Request
创建 Request 之后,会把这个 Request 加到 sessionManger 持有的一个字典中,其读取方法也被加锁了。
var requests: [Int: Request] = [:]
private let lock = NSLock()
/// Access the task delegate for the specified task in a thread-safe manner.
open subscript(task: URLSessionTask) -> Request? {
get {
lock.lock() ; defer { lock.unlock() }
return requests[task.taskIdentifier]
}
set {
lock.lock() ; defer { lock.unlock() }
requests[task.taskIdentifier] = newValue
}
}
处理网络数据
sessionDelegate 接受系统回调
比如方法urlSession(_, task:, didCompleteWithError:)中,会根据 URLSessionTask, 找到对应的 Request。
运行 Request 所有的 validations
运行 TaskDelegate 的任务
所有的任务,都被加到了其持有的 OperationQueue 中。此时处于suspend 状态,要使其处于可运行的状态。
然后加到其中的所有任务,都会开始运行。
去掉对 Request 的持有
Request 已经收到并处理完了网络回调,因此就不必被 sessionDelegate 强持有了。
如果没有其他的持有者,Request 和其TaskDelegate 也会被释放。
其中的同步逻辑
sessionManager 的 DispatchQueue
仅用于创建 URLSessionTask 及部分文件目录操作,都是同步操作。
可能在任何线程创建 URLSessionTask
sessionDelegate 的 lock
仅用于对其持有的Request的读取进行加锁
Request 的 lock
仅对其持有的 TaskDelegate 的读取进行加锁
TaskDelegate 的串行 OperationQueue
其中的 Operation 在数据返回后会执行,并且不会并发。
各种 response 方法,都是在其中加入 Operation
TaskDelegate 的 lock
用于对 urlSessionTask 的读取进行加锁。
URLSessionTask 如何把整体串起来
- 在
sessionManager中被创建 - 初始化
Request时被传入,用来创建TaskDelegate - 被
TaskDelegate持有 - 在
sessionDelegate中,其taskIdentifier被作为索引,来获取Request - 处理回调时,根据
URLSessionTask,可以找到对应的Request,进行对应的处理。
Alamofire源码导读二:发起请求及内部加锁的逻辑的更多相关文章
- Alamofire源码导读一:框架
源码架构  Alamofire 的源码包括 Core.Extensions.Features.Supporting Files.其中主要逻辑在 Core里. 包括构造请求,发起请求,处理回调等. C ...
- 一比一还原axios源码(二)—— 请求响应处理
上一章,我们开发了一些简单的代码,这部分代码最最核心的一个方法就是buildURL,应对了把对象处理成query参数的方方面面.虽然我们现在可以发起简单的请求了,但是第一,我们无法接收到服务器的响应, ...
- Alamofire源码导读四:统计信息
 时间顺序如上图: self.latency = initialResponseTime - requestStartTime self.requestDuration = requestCompl ...
- Alamofire源码导读五:错误表示
AFError is the error type returned by Alamofire. It encompasses a few different types of errors, eac ...
- Alamofire源码导读三:返回的处理逻辑
 以DataRequest 为例子. 最简单的返回 URLSession 有一个方法,可以构建 URLSessionDataTask func dataTask(with url: URL, com ...
- Alamofire源码解读系列(十二)之请求(Request)
本篇是Alamofire中的请求抽象层的讲解 前言 在Alamofire中,围绕着Request,设计了很多额外的特性,这也恰恰表明,Request是所有请求的基础部分和发起点.这无疑给我们一个Req ...
- Alamofire源码解读系列(十二)之时间轴(Timeline)
本篇带来Alamofire中关于Timeline的一些思路 前言 Timeline翻译后的意思是时间轴,可以表示一个事件从开始到结束的时间节点.时间轴的概念能够应用在很多地方,比如说微博的主页就是一个 ...
- Alamofire源码解读系列(二)之错误处理(AFError)
本篇主要讲解Alamofire中错误的处理机制 前言 在开发中,往往最容易被忽略的内容就是对错误的处理.有经验的开发者,能够对自己写的每行代码负责,而且非常清楚自己写的代码在什么时候会出现异常,这样就 ...
- iOS开发之Alamofire源码深度解析
今天博客中的Alamofire源码的版本是以现在最新的3.4版本为例.上篇博客系统的对NSURLSession相关的东西进行了详细的解析,详情请看<详解NSURLSession>,为了就是 ...
随机推荐
- 关于IBatisNet的配置文件中数据库连接字符串加密处理
我们通常在IBatisNet配置文件 properties.config 加入数据库连接字符串.数据库连接字符串直接放在里面,没有被加密,很不安全.如果我们把 properties.config 文件 ...
- KbmMW 服务器架构简介
kbmmw 由于文档比较少,很多同学开始用时很难理解.一直准备写一个关于kbmmw 架构的东西. 这几天与红鱼儿(blog)研究服务器线程时,整理了一下,大概画了一下kbmmw (版本4.5)服务器的 ...
- 2018.10.23 vijo1243生产产品(单调队列优化dp)
传送门 这道单调队列真的有点难写啊. 方程感觉挺简单的. f[i][j]f[i][j]f[i][j]表示在第iii个车间结束前jjj次步骤的最小代价. 然后用单调队列毒瘤优化一下就行了. 代码: #i ...
- 2081.09.22 Kuma(非旋treap)
描述 有N张卡片,编号从0到n-1, 刚开始从0到n-1按顺序排好. 现有一个操作, 对于p. l,表示从第p张卡片之后的l张卡片拿到 最前面. 例如n=7的时候, 刚开始卡片序列为0 1 2 3 4 ...
- MUI框架开发HTML5手机APP(一)--搭建第一个手机APP(转)
出处:http://www.cnblogs.com/jerehedu/p/7832808.html 前 言 JRedu 随着HTML5的不断发展,移动开发成为主流趋势!越来越多的公司开始选择使用H ...
- HDU 2095 find your present (2) (异或)
题意:给定n个数,让你找出那一个次数为1的. 析:由于题意说了,只有那一个数是奇数,所以其他的都是偶数,根据异或的性质,两个相同的数异或为0: 任何数和0异或得原数,可以很简单的做出这个题. 代码如下 ...
- Java中BufferedReader和scanner
Scanner 和BufferedReader同样能实现将键盘输入的数据送入程序, import java.io.*;import java.util.Scanner;public class C { ...
- siganl tappII的应用及MATLAB调用
1.在应用SIGNAL TAPPII时一定要把不用的端口设置为输入三态,否则观察不到数据. 2.用SIGNAL TAPII 观察数据时双向是观察不到数据的,但模块内部用于传输双向口数据的寄存器可以看到 ...
- (最小生成树) Building a Space Station -- POJ -- 2031
链接: http://poj.org/problem?id=2031 Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6011 ...
- Windows 下安装ReText
打算使用MarkDown了,群友推荐使用ReText,基于Python的,同时依赖了Python的几个包,通过easystall可以方便地安装,同时制作了快捷启动方式,网上找了篇文章以备忘. Inst ...