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,進行對應的處理。
相關文章
相關標籤/搜索