mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2026-03-18 20:02:25 +00:00
Fixed segmentation fault crash (#1198)
* Fixed glob segmentation fault * Renamed AtomicDictionary to ThreadSafeDictionary * Refactored ThreadSafeDictionary * ThreadSafeDictionary replaced with ThreadSafeContainer * Removed reader/writer * ThreadSafeContainer replaced with Atomic
This commit is contained in:
committed by
GitHub
parent
be0c3c3926
commit
50aa8c51cc
@@ -8,6 +8,7 @@
|
||||
### Fixed
|
||||
|
||||
- Fix Monterey macOS shell version, shell login flag for environments [#1167](https://github.com/yonaskolb/XcodeGen/issues/1167) @bimawa
|
||||
- Fixed crash caused by a simultaneous write during a glob processing [#1177](https://github.com/yonaskolb/XcodeGen/issues/1177) @tr1ckyf0x
|
||||
|
||||
## 2.27.0
|
||||
|
||||
|
||||
@@ -8,20 +8,45 @@
|
||||
import Foundation
|
||||
|
||||
@propertyWrapper
|
||||
struct Atomic<Value> {
|
||||
private let queue = DispatchQueue(label: "com.xcodegencore.atomic")
|
||||
public final class Atomic<Value> {
|
||||
|
||||
private var value: Value
|
||||
|
||||
init(wrappedValue: Value) {
|
||||
private let queue = DispatchQueue(
|
||||
label: "com.xcodegencore.atomic.\(UUID().uuidString)",
|
||||
qos: .utility,
|
||||
attributes: .concurrent,
|
||||
autoreleaseFrequency: .inherit,
|
||||
target: .global()
|
||||
)
|
||||
|
||||
public init(wrappedValue: Value) {
|
||||
self.value = wrappedValue
|
||||
}
|
||||
|
||||
var wrappedValue: Value {
|
||||
public var wrappedValue: Value {
|
||||
get {
|
||||
return queue.sync { value }
|
||||
queue.sync { value }
|
||||
}
|
||||
set {
|
||||
queue.sync { value = newValue }
|
||||
queue.async(flags: .barrier) { [weak self] in
|
||||
self?.value = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows us to get the actual `Atomic` instance with the $
|
||||
/// prefix.
|
||||
public var projectedValue: Atomic<Value> {
|
||||
return self
|
||||
}
|
||||
|
||||
/// Modifies the protected value using `closure`.
|
||||
public func with<R>(
|
||||
_ closure: (inout Value) throws -> R
|
||||
) rethrows -> R {
|
||||
try queue.sync(flags: .barrier) {
|
||||
try closure(&value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,13 +198,17 @@ public class Glob: Collection {
|
||||
|
||||
var isDirectoryBool = ObjCBool(false)
|
||||
let isDirectory = FileManager.default.fileExists(atPath: path, isDirectory: &isDirectoryBool) && isDirectoryBool.boolValue
|
||||
isDirectoryCache[path] = isDirectory
|
||||
$isDirectoryCache.with { isDirectoryCache in
|
||||
isDirectoryCache[path] = isDirectory
|
||||
}
|
||||
|
||||
return isDirectory
|
||||
}
|
||||
|
||||
private func clearCaches() {
|
||||
isDirectoryCache.removeAll()
|
||||
$isDirectoryCache.with { isDirectoryCache in
|
||||
isDirectoryCache.removeAll()
|
||||
}
|
||||
}
|
||||
|
||||
private func paths(usingPattern pattern: String, includeFiles: Bool) -> [String] {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// AtomicTests.swift
|
||||
//
|
||||
//
|
||||
// Created by Vladislav Lisianskii on 27.03.2022.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import XcodeGenCore
|
||||
|
||||
final class AtomicTests: XCTestCase {
|
||||
|
||||
@Atomic private var atomicDictionary = [String: Int]()
|
||||
|
||||
func testSimultaneousWriteOrder() {
|
||||
let group = DispatchGroup()
|
||||
|
||||
for index in (0..<100) {
|
||||
group.enter()
|
||||
DispatchQueue.global().async {
|
||||
self.$atomicDictionary.with { atomicDictionary in
|
||||
atomicDictionary["\(index)"] = index
|
||||
}
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
|
||||
group.notify(queue: .main, execute: {
|
||||
var expectedValue = [String: Int]()
|
||||
for index in (0..<100) {
|
||||
expectedValue["\(index)"] = index
|
||||
}
|
||||
XCTAssertEqual(
|
||||
self.atomicDictionary,
|
||||
expectedValue
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user