mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Add 'submodules/SSignalKit/' from commit '359b2ee7c9f20f99f221f78e307369ef5ad0ece2'
git-subtree-dir: submodules/SSignalKit git-subtree-mainline:4459dc5b47git-subtree-split:359b2ee7c9
This commit is contained in:
168
submodules/SSignalKit/SwiftSignalKit/ThreadPool.swift
Normal file
168
submodules/SSignalKit/SwiftSignalKit/ThreadPool.swift
Normal file
@@ -0,0 +1,168 @@
|
||||
import Foundation
|
||||
|
||||
public final class ThreadPoolTaskState {
|
||||
public let cancelled = Atomic<Bool>(value: false)
|
||||
}
|
||||
|
||||
public final class ThreadPoolTask {
|
||||
private let state = ThreadPoolTaskState()
|
||||
private let action: (ThreadPoolTaskState) -> ()
|
||||
|
||||
public init(_ action: @escaping(ThreadPoolTaskState) -> ()) {
|
||||
self.action = action
|
||||
}
|
||||
|
||||
func execute() {
|
||||
if !state.cancelled.with { $0 } {
|
||||
self.action(self.state)
|
||||
}
|
||||
}
|
||||
|
||||
public func cancel() {
|
||||
let _ = self.state.cancelled.swap(true)
|
||||
}
|
||||
}
|
||||
|
||||
public final class ThreadPoolQueue : Equatable {
|
||||
private weak var threadPool: ThreadPool?
|
||||
private var tasks: [ThreadPoolTask] = []
|
||||
|
||||
public init(threadPool: ThreadPool) {
|
||||
self.threadPool = threadPool
|
||||
}
|
||||
|
||||
public func addTask(_ task: ThreadPoolTask) {
|
||||
if let threadPool = self.threadPool {
|
||||
threadPool.workOnQueue(self, action: {
|
||||
self.tasks.append(task)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func popFirstTask() -> ThreadPoolTask? {
|
||||
if self.tasks.count != 0 {
|
||||
let task = self.tasks[0];
|
||||
self.tasks.remove(at: 0)
|
||||
return task
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func hasTasks() -> Bool {
|
||||
return self.tasks.count != 0
|
||||
}
|
||||
}
|
||||
|
||||
public func ==(lhs: ThreadPoolQueue, rhs: ThreadPoolQueue) -> Bool {
|
||||
return lhs === rhs
|
||||
}
|
||||
|
||||
@objc public final class ThreadPool: NSObject {
|
||||
private var threads: [Thread] = []
|
||||
private var queues: [ThreadPoolQueue] = []
|
||||
private var takenQueues: [ThreadPoolQueue] = []
|
||||
private var mutex: pthread_mutex_t
|
||||
private var condition: pthread_cond_t
|
||||
|
||||
@objc class func threadEntryPoint(_ threadPool: ThreadPool) {
|
||||
var queue: ThreadPoolQueue!
|
||||
|
||||
while (true) {
|
||||
var task: ThreadPoolTask!
|
||||
|
||||
pthread_mutex_lock(&threadPool.mutex);
|
||||
|
||||
if queue != nil {
|
||||
if let index = threadPool.takenQueues.index(of: queue) {
|
||||
threadPool.takenQueues.remove(at: index)
|
||||
}
|
||||
|
||||
if queue.hasTasks() {
|
||||
threadPool.queues.append(queue);
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
while threadPool.queues.count == 0 {
|
||||
pthread_cond_wait(&threadPool.condition, &threadPool.mutex);
|
||||
}
|
||||
|
||||
if threadPool.queues.count != 0 {
|
||||
queue = threadPool.queues[0]
|
||||
}
|
||||
|
||||
if queue != nil {
|
||||
task = queue.popFirstTask()
|
||||
threadPool.takenQueues.append(queue)
|
||||
|
||||
if let index = threadPool.queues.index(of: queue) {
|
||||
threadPool.queues.remove(at: index)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&threadPool.mutex);
|
||||
|
||||
if task != nil {
|
||||
autoreleasepool {
|
||||
task.execute()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public init(threadCount: Int, threadPriority: Double) {
|
||||
assert(threadCount > 0, "threadCount < 0")
|
||||
|
||||
self.mutex = pthread_mutex_t()
|
||||
self.condition = pthread_cond_t()
|
||||
pthread_mutex_init(&self.mutex, nil)
|
||||
pthread_cond_init(&self.condition, nil)
|
||||
|
||||
super.init()
|
||||
|
||||
for _ in 0 ..< threadCount {
|
||||
let thread = Thread(target: ThreadPool.self, selector: #selector(ThreadPool.threadEntryPoint(_:)), object: self)
|
||||
thread.threadPriority = threadPriority
|
||||
self.threads.append(thread)
|
||||
thread.start()
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
pthread_mutex_destroy(&self.mutex)
|
||||
pthread_cond_destroy(&self.condition)
|
||||
}
|
||||
|
||||
public func addTask(_ task: ThreadPoolTask) {
|
||||
let tempQueue = self.nextQueue()
|
||||
tempQueue.addTask(task)
|
||||
}
|
||||
|
||||
fileprivate func workOnQueue(_ queue: ThreadPoolQueue, action: () -> ()) {
|
||||
pthread_mutex_lock(&self.mutex)
|
||||
action()
|
||||
if !self.queues.contains(queue) && !self.takenQueues.contains(queue) {
|
||||
self.queues.append(queue)
|
||||
}
|
||||
pthread_cond_broadcast(&self.condition)
|
||||
pthread_mutex_unlock(&self.mutex)
|
||||
}
|
||||
|
||||
public func nextQueue() -> ThreadPoolQueue {
|
||||
return ThreadPoolQueue(threadPool: self)
|
||||
}
|
||||
|
||||
public func isCurrentThreadInPool() -> Bool {
|
||||
let currentThread = Thread.current
|
||||
for thread in self.threads {
|
||||
if currentThread.isEqual(thread) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user