QueueSafeValue
提供对值进行线程安全(队列安全)访问的框架。
优势
-
内嵌DispatchSemaphore
只需使用
QueueSafeValue
的特定访问函数(commands
),无需考虑线程同步。 -
内置scheduler
调度器组织同步和异步
commands
的执行。 -
内嵌Comand Queue
(优先队列
)指令队列
用于组织指令的顺序。所有指令将按照优先级顺序逐一执行。 -
优先级指令执行
能够优先更新或访问
QueueSafeValue
。这意味着某些指令将比其他指令运行得更快。 -
不会增加对象引用计数
-
始终返回结果并避免返回可选类型
始终返回
Result<Value, QueueSafeValueError>
-
提供不同的值操作指令
原子指令:
queueSafeValue.wait.lowestPriority.get()
闭包中的值处理指令:
queueSafeValue.wait.lowestPriority.get { result in ... }
闭包中的值访问指令:
queueSafeValue.wait.lowestPriority.set { currentValue in currentVaule = newValue }
文档
命令的基本结构
queueSafeValue.{schedule}.{priority}.{command}
定义
🇨🇳🇴🇲🇦🇳🇩 🇶🇺🇪🇺🇪
- 存储
commands
并按正确的优先级顺序执行它们 QueueSafeValue
内置command queue
(priority queue
),所有closures
(commands
) 都将被放置在其中并执行
🇨🇱🇴🇸🇺🇷🇪🇸
- 是一个访问值的闭包内部
- 从对
value
的并发访问中受到保护(作为critical section
,基于DispatchGroup
的实现)
可用的命令闭包:
commandClosure
- 提供对value
的访问accessClosure
- 提供对值的直接访问(使用inout
关键字)commandCompletionClosure
- 必须始终执行(如果作为属性位于commandClosure
或accessClosure
内部)的闭包。执行闭包通知command queue
命令已完成。之后,command queue
将取消对值的阻塞并执行下一个命令,如果存在的话。
执行方法:
completion commandClosure/accessClosure
- 期望在自身内部使用序列代码的闭包manualCompletion commandClosure/accessClosure
- 期望在自身内部使用序列/异步代码的闭包。此闭包必须手动调用CommandCompletionClosure
,将其作为属性放置在commandClosure
或accessClosure
内部
请求数据组件
🇸🇨🇭🇪🇩🇺🇱🇪
描述 func 将会以同步或异步方式执行
可选的计划:
wait
- (同步)依次执行commands
。阻塞此代码运行的队列,直到任务完成async
- 异步执行被此函数调用的队列中的command
🇵🇷🇮🇴🇷🇮🇹🇾
描述在
命令队列
中command
何时(按什么顺序)执行
可选的优先级:
lowestPriority
- 级别最低的command
将会被最后执行highestPriority
- 级别最高的command
将被最先执行
🇨🇴🇵🇷🇸🇦🇳🇩
描述对
value
的处理(提供对value
的访问)
可用的同步命令
get
同步获取值
1. - 返回
CurrentValue
或QueueSafeValueError
- 当只需要的返回
value
(不处理value
)时使用
func get() -> Result<CurrentValue, QueueSafeValueError>
代码示例
// Option 1
let queueSafeValue = QueueSafeValue(value: true)
DispatchQueue.global(qos: .utility).async {
let result = queueSafeValue.wait.lowestPriority.get()
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
// Option 2
let queueSafeSyncedValue = QueueSafeSyncedValue(value: "a")
DispatchQueue.global(qos: .utility).async {
let result = queueSafeSyncedValue.lowestPriority.get()
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
commandClosure
中同步获取 get
值
2. 在 - 在
commandClosure
内部返回CurrentValue
或QueueSafeValueError
- 当在
commandClosure
中对value
进行处理时,需要保持对value
的读取/写入时,用作critical section
commandClosure
将自动完成
func get(completion commandClosure: ((Result<CurrentValue, QueueSafeValueError>) -> Void)?)
代码示例
// Option 1
let queueSafeValue = QueueSafeValue(value: 6)
DispatchQueue.global(qos: .unspecified).async {
queueSafeValue.wait.lowestPriority.get { result in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
}
// Option 2
let queueSafeSyncedValue = QueueSafeSyncedValue(value: [1,2,3])
DispatchQueue.global(qos: .utility).async {
queueSafeSyncedValue.lowestPriority.get { result in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
}
commandClosure
中手动完成同步获取 get
值
3. 在 - 在
commandClosure
内部返回CurrentValue
或QueueSafeValueError
和CommandCompletionClosure
- 当在
commandClosure
中对value
进行处理时,需要保持对value
的读取/写入时,用作critical section
- 重要:必须通过执行(调用)
CommandCompletionClosure
来手动完成commandClosure
func get(manualCompletion commandClosure: ((Result<CurrentValue, QueueSafeValueError>,
@escaping CommandCompletionClosure) -> Void)?)
代码示例
// Option 1
let queueSafeValue = QueueSafeValue(value: 4.44)
DispatchQueue.global(qos: .unspecified).async {
queueSafeValue.wait.highestPriority.get { result, done in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
done() // Must always be executed (called). Can be called in another DispatchQueue.
}
}
// Option 2
let queueSafeSyncedValue = QueueSafeSyncedValue(value: 4.45)
DispatchQueue.global(qos: .utility).async {
queueSafeSyncedValue.highestPriority.get { result, done in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
done() // Must always be executed (called). Can be called in another DispatchQueue.
}
}
set
值
4. 同步设置 - 返回
UpdatedValue
或QueueSafeValueError
- 当只需要设置
value
(不需要对value
进行处理)时使用
@discardableResult
func set(newValue: Value) -> Result<UpdatedValue, QueueSafeValueError>
代码示例
// Option 1
let queueSafeValue = QueueSafeValue<Int>(value: 1)
DispatchQueue.global(qos: .userInitiated).async {
let result = queueSafeValue.wait.lowestPriority.set(newValue: 2)
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
// Option 2
let queueSafeSyncedValue = QueueSafeSyncedValue(value: "b")
DispatchQueue.global(qos: .userInitiated).async {
let result = queueSafeSyncedValue.lowestPriority.set(newValue: "b1")
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
accessClosure
中同步设置 set
值
5. 在 - 在
accessClosure
内部设置CurrentValue
- 当在一个闭包中需要同时读取和写入
value
时使用 - 当在
accessClosure
处理value
时需要保持对value
的读取/写入时,用作critical section
- 注意:如果发生任何
QueueSafeValueError
,则不会运行accessClosure
@discardableResult
func set(completion accessClosure: ((inout CurrentValue) -> Void)?) -> Result<UpdatedValue, QueueSafeValueError>
代码示例
// Option 1
let queueSafeValue = QueueSafeValue(value: 1)
DispatchQueue.main.async {
let result = queueSafeValue.wait.lowestPriority.set { $0 = 3 }
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
// Option 2
let queueSafeSyncedValue = QueueSafeSyncedValue(value: ["a":1])
DispatchQueue.main.async {
let result = queueSafeSyncedValue.lowestPriority.set { $0["b"] = 2 }
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
accessClosure
中同步设置值,并使用手动完成
6. 在 - 在
accessClosure
内部设置CurrentValue
- 当在一个闭包中需要同时读取和写入
value
时使用 - 当在
accessClosure
处理value
时需要保持对value
的读取/写入时,用作critical section
- 重要:
accessClosure
必须通过执行(调用)CommandCompletionClosure
来手动完成 - 注意: 若出现任何
QueueSafeValueError
,将不会运行accessClosure
。
@discardableResult
func set(manualCompletion accessClosure: ((inout CurrentValue,
@escaping CommandCompletionClosure) -> Void)?) -> Result<UpdatedValue, QueueSafeValueError>
代码示例
// Option 1
let queueSafeValue = QueueSafeValue(value: "value 1")
DispatchQueue.main.async {
let result = queueSafeValue.wait.lowestPriority.set { currentValue, done in
currentValue = "value 2"
done() // Must always be executed (called). Can be called in another DispatchQueue.
}
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
// Option 2
let queueSafeSyncedValue = QueueSafeSyncedValue(value: "value a")
DispatchQueue.main.async {
let result = queueSafeSyncedValue.lowestPriority.set { currentValue, done in
currentValue = "value b"
done() // Must always be executed (called). Can be called in another DispatchQueue.
}
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
commandClosure
中同步映射值
7. 在 - 在
commandClosure
中将CurrentValue
映射到MappedValue
- 当在
commandClosure
中对value
进行处理时,需要保持对value
的读取/写入时,用作critical section
func map<MappedValue>(completion commandClosure: ((CurrentValue) -> MappedValue)?) -> Result<MappedValue, QueueSafeValueError>
代码示例
// Option 1
let queueSafeValue = QueueSafeValue(value: 5)
DispatchQueue.global(qos: .background).async {
let result = queueSafeValue.wait.lowestPriority.map { "\($0)" }
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
// Option 2
let queueSafeSyncedValue = QueueSafeSyncedValue(value: "1")
DispatchQueue.global(qos: .background).async {
let result = queueSafeSyncedValue.lowestPriority.map { Int($0) }
switch result {
case .failure(let error): print(error)
case .success(let value): print(String(describing: value))
}
}
可用的异步命令
commandClosure
中异步获取值
1. 在 - 在
commandClosure
中返回CurrentValue
或QueueSafeValueError
- 当在
commandClosure
中对value
进行处理时,需要保持对value
的读取/写入时,用作critical section
commandClosure
将自动完成
func get(completion commandClosure: ((Result<CurrentValue, QueueSafeValueError>) -> Void)?)
代码示例
// Option 1
let queueSafeValue = QueueSafeValue(value: true)
queueSafeValue.async(performIn: .global(qos: .utility)).highestPriority.get { result in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
// Option 2
let queueSafeAsyncedValue = QueueSafeAsyncedValue(value: true, queue: .global(qos: .utility))
queueSafeAsyncedValue.highestPriority.get { result in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
commandClosure
中异步获取值,并使用手动完成
2. 在 - 在
commandClosure
内部返回CurrentValue
或QueueSafeValueError
和CommandCompletionClosure
- 当在
commandClosure
中对value
进行处理时,需要保持对value
的读取/写入时,用作critical section
- 重要:必须通过执行(调用)
CommandCompletionClosure
来手动完成commandClosure
func get(manualCompletion commandClosure: ((Result<CurrentValue, QueueSafeValueError>,
@escaping CommandCompletionClosure) -> Void)?)
代码示例
// Option 1
let queueSafeValue = QueueSafeValue(value: "test")
queueSafeValue.async(performIn: .global(qos: .utility)).highestPriority.get { result, done in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
done() // Must always be executed (called). Can be called in another DispatchQueue.
}
// Option 2
let queueSafeAsyncedValue = QueueSafeAsyncedValue(value: "super test", queue: .global(qos: .background))
queueSafeAsyncedValue.highestPriority.get { result, done in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
done() // Must always be executed (called). Can be called in another DispatchQueue.
}
set
value 同步
3. - 在
commandClosure
中返回UpdatedValue
或QueueSafeValueError
- 当只需要设置
value
(不需要对value
进行处理)时使用
func set(newValue: Value, completion commandClosure: ((Result<UpdatedValue, QueueSafeValueError>) -> Void)? = nil)
代码示例
// Option 1
let queueSafeValue = QueueSafeValue(value: 7)
// Without completion block
queueSafeValue.async(performIn: .main).highestPriority.set(newValue: 8)
// With completion block
queueSafeValue.async(performIn: .main).highestPriority.set(newValue: 9) { result in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
// Option 2
let queueSafeAsyncedValue = QueueSafeAsyncedValue(value: 7, queue: .global())
// Without completion block
queueSafeAsyncedValue.highestPriority.set(newValue: 8)
// With completion block
queueSafeAsyncedValue.highestPriority.set(newValue: 9) { result in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
set
value 同步在 accessClosure
中
4. - 在
accessClosure
内部设置CurrentValue
- 当在一个闭包中需要同时读取和写入
value
时使用 - 当在
accessClosure
处理value
时需要保持对value
的读取/写入时,用作critical section
- 注意:如果发生任何
QueueSafeValueError
,则不会运行accessClosure
func set(accessClosure: ((inout CurrentValue) -> Void)?,
completion commandClosure: ((Result<UpdatedValue, QueueSafeValueError>) -> Void)? = nil)
代码示例
// Option 1.
let queueSafeValue = QueueSafeValue(value: 1)
// Without completion block
queueSafeValue.async(performIn: .background).highestPriority.set { $0 = 10 }
// With completion block
queueSafeValue.async(performIn: .background).highestPriority.set { currentValue in
currentValue = 11
} completion: { result in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
// Option 2.
let queueSafeAsyncedValue = QueueSafeAsyncedValue(value: 1, queue: .global(qos: .userInteractive))
// Without completion block
queueSafeAsyncedValue.highestPriority.set { $0 = 10 }
// With completion block
queueSafeAsyncedValue.highestPriority.set { currentValue in
currentValue = 11
} completion: { result in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
set
value 同步在 accessClosure
中,带有手动完成
5. - 在
accessClosure
内部设置CurrentValue
- 当在一个闭包中需要同时读取和写入
value
时使用 - 当在
accessClosure
处理value
时需要保持对value
的读取/写入时,用作critical section
- 重要:
accessClosure
必须通过执行(调用)CommandCompletionClosure
来手动完成 - 注意: 若出现任何
QueueSafeValueError
,将不会运行accessClosure
。
func set(manualCompletion accessClosure: ((inout CurrentValue, @escaping CommandCompletionClosure) -> Void)?,
completion commandClosure: ((Result<UpdatedValue, QueueSafeValueError>) -> Void)? = nil)
代码示例
// Option 1.
let queueSafeValue = QueueSafeValue(value: 999.1)
// Without completion block
queueSafeValue.async(performIn: .background).highestPriority.set { currentValue, done in
currentValue = 999.2
done() // Must always be executed (called). Can be called in another DispatchQueue.
}
// With completion block
queueSafeValue.async(performIn: .background).highestPriority.set { currentValue, done in
currentValue = 999.3
done() // Must always be executed (called). Can be called in another DispatchQueue.
} completion: { result in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
// Option 2.
let queueSafeAsyncedValue = QueueSafeAsyncedValue(value: 1000.1, queue: .global(qos: .userInteractive))
// Without completion block
queueSafeAsyncedValue.highestPriority.set { currentValue, done in
currentValue = 1000.2
done() // Must always be executed (called). Can be called in another DispatchQueue.
}
// With completion block
queueSafeAsyncedValue.highestPriority.set { currentValue, done in
currentValue = 1000.3
done() // Must always be executed (called). Can be called in another DispatchQueue.
} completion: { result in
switch result {
case .failure(let error): print(error)
case .success(let value): print(value)
}
}
需求
- iOS 8.0+
- Xcode 10+
- Swift 5.1+
安装
步骤 1
QueueSafeValue 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile 中
pod 'QueueSafeValue'
步骤 2
在项目根目录下运行 pod install
步骤 3
要使用已安装的 QueueSafeValue
框架,只需在你要应用它的 swift 文件中导入 QueueSafeValue
。
作者
瓦西里·博德纳尔丘克,https://www.linkedin.com/in/vasily-bodnarchuk/
许可证
QueueSafeValue 适用于 MIT 许可证。有关更多信息,请参阅 LICENSE 文件。