fix: DateFormattersReusePool and ISO8601DateFormattersReusePool are now thread safe

This commit is contained in:
Ivan Smolin 2022-04-27 11:29:20 +03:00
parent e31283cb67
commit d568963784
20 changed files with 76 additions and 18 deletions

View File

@ -1,5 +1,9 @@
# Changelog
### 1.16.1
- **Update**: `DateFormattersReusePool` and `ISO8601DateFormattersReusePool` are now thread safe.
### 1.16.0
- **Add**: `TIMapUtils`, `TIAppleMapUtils`, `TIGoogleMapUtils` and `TIYandexMapUtils` modules for map items clustering and interacting with them.

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "LeadKit"
s.version = "1.16.0"
s.version = "1.16.1"
s.summary = "iOS framework with a bunch of tools for rapid development"
s.homepage = "https://github.com/TouchInstinct/LeadKit"
s.license = "Apache License, Version 2.0"

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIAppleMapUtils'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Set of helpers for map objects clustering and interacting using Apple MapKit.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -28,7 +28,7 @@ import Foundation
// than to create and dispose of multiple instances.
// (https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW10)
open class DateFormattersReusePool {
private var pool: [String: DateFormatter] = [:]
private var pool: ThreadSafeDictionary<String, DateFormatter> = [:]
private let presetLocale: Locale?
private let presetTimeZone: TimeZone?

View File

@ -23,7 +23,7 @@
import Foundation
open class ISO8601DateFormattersReusePool {
private var pool: [ISO8601DateFormatter.Options: ISO8601DateFormatter] = [:]
private var pool: ThreadSafeDictionary<ISO8601DateFormatter.Options, ISO8601DateFormatter> = [:]
private let presetTimeZone: TimeZone?

View File

@ -0,0 +1,54 @@
import Dispatch
public final class ThreadSafeDictionary<K: Hashable, V>: Collection, ExpressibleByDictionaryLiteral {
private var wrappedDict: [K: V]
private let concurrentQueue = DispatchQueue(label: "TIFoundationUtils.ThreadSafeDictionary.Queue",
attributes: .concurrent)
// MARK: - Collection
public var startIndex: Dictionary<K, V>.Index {
concurrentQueue.sync {
self.wrappedDict.startIndex
}
}
public var endIndex: Dictionary<K, V>.Index {
concurrentQueue.sync {
self.wrappedDict.endIndex
}
}
// MARK: - ExpressibleByDictionaryLiteral
public init(dictionaryLiteral elements: (K, V)...) {
self.wrappedDict = Dictionary(uniqueKeysWithValues: elements)
}
// MARK: - Collection
public func index(after i: Dictionary<K, V>.Index) -> Dictionary<K, V>.Index {
concurrentQueue.sync {
self.wrappedDict.index(after: i)
}
}
public subscript(index: Dictionary<K, V>.Index) -> Dictionary<K, V>.Element {
concurrentQueue.sync {
self.wrappedDict[index]
}
}
public subscript(key: K) -> V? {
set {
concurrentQueue.async(flags: .barrier) {
self.wrappedDict[key] = newValue
}
}
get {
concurrentQueue.sync {
self.wrappedDict[key]
}
}
}
}

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIFoundationUtils'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Set of helpers for Foundation framework classes.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIGoogleMapUtils'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Set of helpers for map objects clustering and interacting using Google Maps SDK.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIKeychainUtils'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Set of helpers for Keychain classes.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIMapUtils'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Set of helpers for map objects clustering and interacting.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIMoyaNetworking'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Moya + Swagger network service.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TINetworking'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Swagger-frendly networking layer helpers.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TINetworkingCache'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Caching results of EndpointRequests.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIPagination'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Generic pagination component.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TISwiftUtils'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Bunch of useful helpers for Swift development.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TITableKitUtils'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Set of helpers for TableKit classes.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TITransitions'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Set of custom transitions to present controller. '
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIUIElements'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Bunch of useful protocols and views.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIUIKitCore'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Core UI elements: protocols, views and helpers.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIYandexMapUtils'
s.version = '1.16.0'
s.version = '1.16.1'
s.summary = 'Set of helpers for map objects clustering and interacting using Yandex Maps SDK.'
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
s.license = { :type => 'MIT', :file => 'LICENSE' }