Change some types from class to struct to avoid data racing (#33)

* Change the type of ChangePack from class to struct
* Change ``Change`` and types confirming ``Operation``  from class to struct
This commit is contained in:
원형식 2022-11-10 09:41:54 +09:00 committed by GitHub
parent b91f55d056
commit ab0d8c92e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 25 additions and 16 deletions

View File

@ -19,11 +19,11 @@ import Foundation
/**
* `Change` represents a unit of modification in the document.
*/
class Change {
struct Change {
private var id: ChangeID
// `operations` represent a series of user edits.
private let operations: [Operation]
private var operations: [Operation]
// `message` is used to save a description of the change.
private let message: String?
@ -58,11 +58,14 @@ class Change {
/**
* `setActor` sets the given actor.
*/
func setActor(_ actorID: ActorID) {
self.operations.forEach {
$0.setActor(actorID)
mutating func setActor(_ actorID: ActorID) {
let operations = self.operations.map {
var new = $0
new.setActor(actorID)
return new
}
self.operations = operations
self.id.setActor(actorID)
}

View File

@ -19,7 +19,7 @@ import Foundation
/**
* `ChangePack` is a unit for delivering changes in a document to the remote.
*/
class ChangePack {
struct ChangePack {
/**
* `documentKey` is the key of the document.
*/
@ -41,7 +41,7 @@ class ChangePack {
* `minSyncedTicket` is the minimum logical time taken by clients who attach
* the document. It used to collect garbage on the replica on the client.
*/
private var minSyncedTicket: TimeTicket?
private let minSyncedTicket: TimeTicket?
init(key: String, checkpoint: Checkpoint, changes: [Change], snapshot: Data? = nil, minSyncedTicket: TimeTicket? = nil) {
self.documentKey = key

View File

@ -148,9 +148,14 @@ public actor Document {
*
*/
func setActor(_ actorID: ActorID) {
for change in self.localChanges {
change.setActor(actorID)
let changes = self.localChanges.map {
var new = $0
new.setActor(actorID)
return new
}
self.localChanges = changes
self.changeID.setActor(actorID)
// TODOs also apply into root.

View File

@ -19,7 +19,7 @@ import Foundation
/**
* `AddOperation` is an operation representing adding an element to an Array.
*/
class AddOperation: Operation {
struct AddOperation: Operation {
let parentCreatedAt: TimeTicket
var executedAt: TimeTicket
private var previousCreatedAt: TimeTicket

View File

@ -19,7 +19,7 @@ import Foundation
/**
* `MoveOperation` is an operation representing moving an element to an Array.
*/
class MoveOperation: Operation {
struct MoveOperation: Operation {
let parentCreatedAt: TimeTicket
var executedAt: TimeTicket
private var previousCreatedAt: TimeTicket

View File

@ -18,8 +18,9 @@ import Foundation
/**
* `Operation` represents an operation to be executed on a document.
* Types confiming ``Operation`` must be struct to avoid data racing.
*/
protocol Operation: AnyObject {
protocol Operation {
var parentCreatedAt: TimeTicket { get }
var executedAt: TimeTicket { get set }
@ -58,7 +59,7 @@ extension Operation {
/**
* `setActor` sets the given actor to this operation.
*/
func setActor(_ actorID: ActorID) {
mutating func setActor(_ actorID: ActorID) {
self.executedAt.setActor(actorID)
}
}

View File

@ -19,7 +19,7 @@ import Foundation
/**
* `RemoveOperation` is an operation representing removes an element from Container.
*/
class RemoveOperation: Operation {
struct RemoveOperation: Operation {
let parentCreatedAt: TimeTicket
var executedAt: TimeTicket
private var createdAt: TimeTicket

View File

@ -20,7 +20,7 @@ import Foundation
* `SetOperation` represents an operation that stores the value corresponding to the
* given key in the Object.
*/
class SetOperation: Operation {
struct SetOperation: Operation {
let parentCreatedAt: TimeTicket
var executedAt: TimeTicket
private let key: String

View File

@ -42,7 +42,7 @@ class ChangeTests: XCTestCase {
let changeID = ChangeID(clientSeq: 1, lamport: 2, actor: self.actorId)
let target = Change(id: changeID, operations: [setOperation])
var target = Change(id: changeID, operations: [setOperation])
XCTAssertEqual(target.getOperations()[0].executedAt.getStructureAsString(), "8:actor-1:0")