以创建一个 DataRequest 为例子

发起请求

创建 SessionManager

顺带也创建了一个 SessionDelegate
持有一个urlSession,持有一个串行的 DispatchQueue A
注意,这个不是urlSession 回调方法执行时所在的OperationQueue

创建 Requestable 的 struct,并创建underlying 的 URLSessionDataTask

目前不太清楚作用是什么,但是文档上的注释写着 Helper Types
持有一个 urlRequest
然后使用这个 Requestable,创建一个 URLSessionDataTask
注意要在SessionManager持有的串行队列中同步创建

sessionManager 创建一个 Request 对象

通过传入参数 URLSessionDataTaskurlSession
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源码导读二:发起请求及内部加锁的逻辑的更多相关文章

  1. Alamofire源码导读一:框架

    源码架构  Alamofire 的源码包括 Core.Extensions.Features.Supporting Files.其中主要逻辑在 Core里. 包括构造请求,发起请求,处理回调等. C ...

  2. 一比一还原axios源码(二)—— 请求响应处理

    上一章,我们开发了一些简单的代码,这部分代码最最核心的一个方法就是buildURL,应对了把对象处理成query参数的方方面面.虽然我们现在可以发起简单的请求了,但是第一,我们无法接收到服务器的响应, ...

  3. Alamofire源码导读四:统计信息

     时间顺序如上图: self.latency = initialResponseTime - requestStartTime self.requestDuration = requestCompl ...

  4. Alamofire源码导读五:错误表示

    AFError is the error type returned by Alamofire. It encompasses a few different types of errors, eac ...

  5. Alamofire源码导读三:返回的处理逻辑

     以DataRequest 为例子. 最简单的返回 URLSession 有一个方法,可以构建 URLSessionDataTask func dataTask(with url: URL, com ...

  6. Alamofire源码解读系列(十二)之请求(Request)

    本篇是Alamofire中的请求抽象层的讲解 前言 在Alamofire中,围绕着Request,设计了很多额外的特性,这也恰恰表明,Request是所有请求的基础部分和发起点.这无疑给我们一个Req ...

  7. Alamofire源码解读系列(十二)之时间轴(Timeline)

    本篇带来Alamofire中关于Timeline的一些思路 前言 Timeline翻译后的意思是时间轴,可以表示一个事件从开始到结束的时间节点.时间轴的概念能够应用在很多地方,比如说微博的主页就是一个 ...

  8. Alamofire源码解读系列(二)之错误处理(AFError)

    本篇主要讲解Alamofire中错误的处理机制 前言 在开发中,往往最容易被忽略的内容就是对错误的处理.有经验的开发者,能够对自己写的每行代码负责,而且非常清楚自己写的代码在什么时候会出现异常,这样就 ...

  9. iOS开发之Alamofire源码深度解析

    今天博客中的Alamofire源码的版本是以现在最新的3.4版本为例.上篇博客系统的对NSURLSession相关的东西进行了详细的解析,详情请看<详解NSURLSession>,为了就是 ...

随机推荐

  1. 1、HttpClient初探

    HttpClient是它的核心接口.可以理解为一个简单的浏览器. 主要方法有: getParams();   获取运行参数 getConnectionManager(); 获取连接管理器.连接管理器中 ...

  2. 2018.09.16 bzoj3626: [LNOI2014]LCA(树链剖分)

    传送门 树链剖分好题. 对于每个点维护一个值vi" role="presentation" style="position: relative;"&g ...

  3. UVa 10269 Adventure of Super Mario (Floyd + DP + BFS)

    题意:有A个村庄,B个城市,m条边,从起点到终点,找一条最短路径.但是,有一种工具可以使人不费力的移动L个长度,但始末点必须是城市或村庄.这种工具有k个,每个只能使用一次,并且在城市内部不可使用,但在 ...

  4. AngularJS标准Web业务流程开发框架—1.AngularJS模块以及启动分析

    前言: AngularJS中提到模块是自定义的模块标准,提到这不得不说AngularJS是框架中的老大哥,思想相当的前卫..在这框架满天横行的时代,AngularJS有些思想至今未被超越,当然仁者见仁 ...

  5. 20170908工作日记--Volley源码详解

    Volley没有jar包,需要从官网上下载源码自己编译出来,或者做成相关moudle引入项目中.我们先从最简单的使用方法入手进行分析: //创建一个网络请求队列 RequestQueue reques ...

  6. struts2从浅至深(六)总结

    在我认为strust2的作用就是 1.主要跟前端交互的框架数据提交先经过struts 2.起到对数据的过滤,接受数据 3.把数据显示到前段,具有很成熟的ognl技术,用起来特别方便 4.还提供了跟前段 ...

  7. python logging 实现的进程安全的文件回滚日志类

    python标准库中的logging模块在记录日志时经常会用到,但在实际使用发现它自带的用于本地日志回滚的类 logging.handlers.RotatingFileHandler 在多进程环境下会 ...

  8. (匹配)Antenna Placement --POJ --3020

    链接: http://poj.org/problem?id=3020 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82834#probl ...

  9. Codeforces777B Game of Credit Cards 2017-05-04 17:19 29人阅读 评论(0) 收藏

    B. Game of Credit Cards time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  10. Flash CC2015软件安装教程

    FLCC2015/64位下载地址: 链接:https://pan.baidu.com/s/1c1WoTTu 密码:k4hn 软件介绍: Flash是一种动画创作与应用程序开发于一身的创作软件.Flas ...