Currently I rework my projects for Swift 6.
Now I have an error
Static property 'wName' is not concurrency-safe because it is nonisolated global shared mutable state
I'm not sure how to solve this issue without a complete rework of the application structure. It is a command line app where the main code calls
MBackup.doSomething(…)
…
MBackup.cleanUp(…)
and the class is defined in this way
class MBackup : BackupBase {
static var wName : String?
class func doSomething(…) -> Bool {
// initialize all
self.Name = getName(…)
// do some work
}
class func cleanUp(…) {
// use/access wName
}
Do I miss something to get an easy concurrency-safe way to solve this issue?
Static mutable properties are generally not safe because they can be concurrently modified from any thread/actor, and this is what the compiler error is trying to communitate. There are multiple ways to fix this:
If you don't even need to write to wName, make it a static let instead of static var.
If you still need to mutate it occasionally, wrap it into a Mutex (the new concurrency primitive available in the Standard Library with Swift 6.0 and the newest Apple OS releases) or e.g. OSAllocatedUnfairLock for former Apple OS versions.
Make MBackup an actor, the static property will become isolated to it.
Constrain it to some global actor, perhaps alongside with the whole MBackup class that needs to access it. This way, all reads and writes to it will be serialized.
Make it nonisolated(unsafe). If it's only accessed from the MBackup class, and you can make sure by other means that all accesses are serialized, you can simply tell the compiler to ignore the concurrency-safety in this instance. It'd also help to perhaps make it private so that you don't accidentally access it from outside. This fix is typically the last resort, though.
The first two and the last options lean more in the direction of not requiring a complete app rework.
Also if you only use this static property from MainActor you can annotate it as @MainActor (or the whole type). If you are using it from different contexts (actors, queues, threads etc) than you had the problem all along and I would suggest following @nkbelov 's points
If I understand correctly, doSomething in your case is more like a one-time initialization rather than a repeated call. What you could do instead if program logic allows it is to initialize the value through a lazily evaluated closure instead (while converting the variable to a let):
static let wName : String? = {
// some logic
return name
}()