Reputation: 2529
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
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