implement a safe concurrent dictionary

This commit is contained in:
Alex Zenla 2024-09-01 22:30:47 -04:00
parent a149de885c
commit 65af0b321d
No known key found for this signature in database
GPG Key ID: 067B238899B51269
3 changed files with 78 additions and 6 deletions

View File

@ -7,6 +7,9 @@ add_executable(Voxelotl MACOSX_BUNDLE
shadertypes.h
shader.metal
# Common library
Common/ConcurrentDictionary.swift
# Maths library
Math/FloatExtensions.swift
Math/IntegerExtensions.swift
@ -98,6 +101,7 @@ set_source_files_properties(test.png PROPERTIES MACOSX_PACKAGE_LOCATION Resource
#TODO: should use TREE mode as documented in https://cmake.org/cmake/help/latest/command/source_group.html
source_group("Resources" FILES Assets.xcassets test.png)
source_group("Source Files\\Common" REGULAR_EXPRESSION "Common/")
source_group("Source Files" REGULAR_EXPRESSION "\\.(swift|metal)$")
source_group("Source Files\\Random" REGULAR_EXPRESSION "Random/")
source_group("Source Files\\Math" REGULAR_EXPRESSION "Math/")

View File

@ -0,0 +1,73 @@
import Foundation
public class ConcurrentDictionary<V: Hashable, T>: Collection {
private var inner: [V : T]
private var lock: NSLock = .init()
public var keys: Dictionary<V, T>.Keys {
self.locked {
inner.keys
}
}
public var values: Dictionary<V, T>.Values {
self.locked {
self.inner.values
}
}
public var startIndex: Dictionary<V, T>.Index {
self.locked {
self.inner.startIndex
}
}
public var endIndex: Dictionary<V, T>.Index {
self.locked {
self.inner.endIndex
}
}
public init(inner: [V:T]) {
self.inner = inner
}
public convenience init() {
self.init(inner: [:])
}
public func index(after i: Dictionary<V, T>.Index) -> Dictionary<V, T>.Index {
self.locked {
self.inner.index(after: i)
}
}
public subscript(key: V) -> T? {
set(newValue) {
self.locked {
self.inner[key] = newValue
}
}
get {
self.locked {
self.inner[key]
}
}
}
public subscript(index: Dictionary<V, T>.Index) -> Dictionary<V, T>.Element {
self.locked {
self.inner[index]
}
}
fileprivate func locked<X>(_ perform: () -> X) -> X {
self.lock.lock()
defer {
self.lock.unlock()
}
let value = perform()
return value
}
}

View File

@ -63,8 +63,7 @@ public class World {
self._generator.reset(seed: seed)
let orig = SIMD3(width, height, depth) / 2
var localChunks: [SIMD3<Int>: Chunk] = [:]
let localChunksLock = NSLock()
let localChunks = ConcurrentDictionary<SIMD3<Int>, Chunk>()
let queue = OperationQueue()
queue.qualityOfService = .userInitiated
for z in 0..<depth {
@ -73,10 +72,6 @@ public class World {
let chunkID = SIMD3(x, y, z) &- orig
queue.addOperation {
let chunk = self._generator.makeChunk(id: chunkID)
localChunksLock.lock()
defer {
localChunksLock.unlock()
}
localChunks[chunkID] = chunk
}
}