Alamofire源码导读二:发起请求及内部加锁的逻辑

以建立一个 DataRequest 为例子 网络

发起请求

建立 SessionManager

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

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

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

sessionManager 建立一个 Request 对象

经过传入参数 URLSessionDataTaskurlSession
Request 会持有传入的 urlSession,并根据URLSessionDataTask,建立一个 TaskDelegate。 外部对这个TaskDelegate 的读取,被锁保护起来了。 url

/// 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 状态。 spa

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, 找到对应的 Requestcode

运行 Request 全部的 validations

运行 TaskDelegate 的任务

全部的任务,都被加到了其持有的 OperationQueue 中。此时处于suspend 状态,要使其处于可运行的状态。
而后加到其中的全部任务,都会开始运行。 对象

去掉对 Request 的持有

Request 已经收到并处理完了网络回调,所以就没必要被 sessionDelegate 强持有了。
若是没有其余的持有者,Request 和其TaskDelegate 也会被释放。 blog

其中的同步逻辑

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,进行对应的处理。
相关文章
相关标签/搜索