From 023f1d784720731fbcd3ac537ac1836b1c0c7797 Mon Sep 17 00:00:00 2001 From: Jung gyun Ahn Date: Fri, 28 Jun 2024 20:52:59 +0900 Subject: [PATCH] Add lock (#185) * Add a semaphore for serialize document update * Open isApplyingChangePack variable * Revert add isApplyingChagePack variable * Add defer closure to signal semaphore. --- .../xcshareddata/swiftpm/Package.resolved | 18 ++++++++++++++++ Sources/Document/Document.swift | 21 ++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Examples/Example.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/Example.xcworkspace/xcshareddata/swiftpm/Package.resolved index 705bc521..ec3d128d 100644 --- a/Examples/Example.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Examples/Example.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -36,6 +36,24 @@ "version" : "1.1.0" } }, + { + "identity" : "swift-docc-plugin", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-plugin", + "state" : { + "revision" : "26ac5758409154cc448d7ab82389c520fa8a8247", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-docc-symbolkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-symbolkit", + "state" : { + "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34", + "version" : "1.0.0" + } + }, { "identity" : "swift-log", "kind" : "remoteSourceControl", diff --git a/Sources/Document/Document.swift b/Sources/Document/Document.swift index c3a697d6..ac062c7f 100644 --- a/Sources/Document/Document.swift +++ b/Sources/Document/Document.swift @@ -16,6 +16,7 @@ import Combine import Foundation +import Semaphore /** * `DocumentOptions` are the options to create a new document. @@ -99,6 +100,8 @@ public actor Document { */ private var presences: [ActorID: StringValueTypeDictionary] + private let workSemaphore = AsyncSemaphore(value: 1) + public init(key: String) { self.init(key: key, opts: DocumentOptions(disableGC: false)) } @@ -120,7 +123,13 @@ public actor Document { /** * `update` executes the given updater to update this document. */ - public func update(_ updater: (_ root: JSONObject, _ presence: inout Presence) throws -> Void, _ message: String? = nil) throws { + public func update(_ updater: (_ root: JSONObject, _ presence: inout Presence) async throws -> Void, _ message: String? = nil) async throws { + await self.workSemaphore.wait() + + defer { + self.workSemaphore.signal() + } + guard self.status != .removed else { throw YorkieError.documentRemoved(message: "\(self) is removed.") } @@ -141,7 +150,7 @@ public actor Document { var presence = Presence(changeContext: context, presence: self.clone?.presences[actorID] ?? [:]) - try updater(proxy, &presence) + try await updater(proxy, &presence) self.clone?.presences[actorID] = presence.presence @@ -250,7 +259,13 @@ public actor Document { * * - Parameter pack: change pack */ - func applyChangePack(_ pack: ChangePack) throws { + func applyChangePack(_ pack: ChangePack) async throws { + await self.workSemaphore.wait() + + defer { + self.workSemaphore.signal() + } + if let snapshot = pack.getSnapshot() { try self.applySnapshot(pack.getCheckpoint().getServerSeq(), snapshot) } else if pack.hasChanges() {