diff --git a/Sources/Voxelotl/CMakeLists.txt b/Sources/Voxelotl/CMakeLists.txt index ec4b1c8..a4cee82 100644 --- a/Sources/Voxelotl/CMakeLists.txt +++ b/Sources/Voxelotl/CMakeLists.txt @@ -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/") diff --git a/Sources/Voxelotl/Common/ConcurrentDictionary.swift b/Sources/Voxelotl/Common/ConcurrentDictionary.swift new file mode 100644 index 0000000..3a1907e --- /dev/null +++ b/Sources/Voxelotl/Common/ConcurrentDictionary.swift @@ -0,0 +1,73 @@ +import Foundation + +public class ConcurrentDictionary: Collection { + private var inner: [V : T] + private var lock: NSLock = .init() + + public var keys: Dictionary.Keys { + self.locked { + inner.keys + } + } + + public var values: Dictionary.Values { + self.locked { + self.inner.values + } + } + + public var startIndex: Dictionary.Index { + self.locked { + self.inner.startIndex + } + } + + public var endIndex: Dictionary.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.Index) -> Dictionary.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.Index) -> Dictionary.Element { + self.locked { + self.inner[index] + } + } + + fileprivate func locked(_ perform: () -> X) -> X { + self.lock.lock() + defer { + self.lock.unlock() + } + let value = perform() + return value + } +} diff --git a/Sources/Voxelotl/World.swift b/Sources/Voxelotl/World.swift index 33984d9..b1517ff 100644 --- a/Sources/Voxelotl/World.swift +++ b/Sources/Voxelotl/World.swift @@ -62,15 +62,26 @@ public class World { func generate(width: Int, height: Int, depth: Int, seed: UInt64) { self._generator.reset(seed: seed) let orig = SIMD3(width, height, depth) / 2 + + let localChunks = ConcurrentDictionary() + let queue = OperationQueue() + queue.qualityOfService = .userInitiated for z in 0..