Zmey
Zmey

Reputation: 2529

How to create a non-atomic global or static variable in Swift

Often I need to cache a value to reuse it in multiple instances of a class, for example:

class Session {
    typealias T = Session

    let chatId: Int64
    let userId: Int64
    var name = ""
    var url = ""

    // ------- Define schema helpers --------
    // The problem: access to them is dispatch_once-d.
    static let table = Table("Session")
    static let chatIdColumn = Expression<Int64>("ChatId")
    static let userIdColumn = Expression<Int64>("UserId")
    static let nameColumn = Expression<String>("Name")
    static let urlColumn = Expression<String>("Url")

    init() {
        ...
        // ------ They're used in constructor: ------
        guard let chat = db.pluckItem(T.table, T.chatIdColumn, chatId)
            else { return }

        userId = wish[T.userIdColumn]
        name = wish[T.nameColumn]
        url = wish[T.urlColumn]
    }

    func save() throws {
        // ------ They're also used when saving the object back to DB ------
        ...
        try db.upsert(T.table, T.wishIdColumn, wishId, setters:
            T.userIdColumn <- userId,
            T.nameColumn <- name,
            T.urlColumn <- url
    )

    func other() {
        // ------ Sometimes they're used in other methods of the class ------
    }
}

Static and global variables are lazily atomically initialized with dispatch_once, so accessing them involves some overhead. (See Jckarter's response on https://devforums.apple.com/thread/229436)

Is there a way to cache the value non-atomically? In most cases I don't need thread safety and variables are used internally inside of class implementation.

Simply declaring non-static instance variables is not an option because the value can be expensive to compute or too big to store in each class instance.

Of course, I can create a separate class for these shared properties and store a reference to it in a member variable of EACH object, but this complicates the implementation unnecessarily and adds memory overhead.

Upvotes: 4

Views: 1107

Answers (1)

fumoboy007
fumoboy007

Reputation: 5543

Read this: https://mikeash.com/pyblog/friday-qa-2014-06-06-secrets-of-dispatch_once.html.

That article dives into the implementation of dispatch_once and compares its performance to that of the non-thread-safe equivalent. The conclusion is that there is no overhead on subsequent reads of the variable after the initial write to the variable.

Therefore, I think you should spend your time elsewhere. :-)

Upvotes: 5

Related Questions