Skip to content

Instantly share code, notes, and snippets.

@ttepasse
Last active August 29, 2015 14:15
Show Gist options
  • Save ttepasse/5e022231f690afe4ac0b to your computer and use it in GitHub Desktop.
Save ttepasse/5e022231f690afe4ac0b to your computer and use it in GitHub Desktop.
class CostlyAllocatedObject {
var description : String
init(_ isPrivate: Bool, _ isStarred: Bool, _ isUnread: Bool) {
self.description = "<Costly: Private: \(isPrivate), Starred \(isStarred), Unread: \(isUnread)>"
}
}
class ReallocateIfNeeded<T> {
private var cachedInstance: T? = nil
private var needsReallocation: Bool
private var callToAllocateInstance: () -> T
init(allocationProcedure: () -> T) {
self.needsReallocation = true
self.callToAllocateInstance = allocationProcedure
}
func invalidate() {
self.needsReallocation = true
}
func mayNeedReallocationIf(@autoclosure test: () -> Bool) {
if test() {
self.invalidate()
}
}
var instance : T {
get {
if self.needsReallocation {
println("(Re)-Allocating Costly")
self.cachedInstance = self.callToAllocateInstance()
self.needsReallocation = false
return self.cachedInstance!
} else {
println("Returning cached Costly")
return self.cachedInstance!
}
}
}
}
class Usage {
var isPrivate: Bool? = nil {
didSet {
println("isPrivate: comparing new value (\(self.isPrivate!)) to old value (\(oldValue!))")
costly.mayNeedReallocationIf( self.isPrivate != oldValue )
}
}
var isStarred: Bool? = nil {
didSet {
println("isStarred: comparing new value (\(self.isStarred!)) to old value (\(oldValue!))")
costly.mayNeedReallocationIf( self.isStarred != oldValue )
}
}
var isUnread: Bool? = nil {
didSet {
println("isUnread: comparing new value (\(self.isUnread!)) to old value (\(oldValue!))")
costly.mayNeedReallocationIf( self.isUnread != oldValue )
}
}
init () {
self.isUnread = true
self.isStarred = true
self.isPrivate = true
}
// lazy is needed for the presence of self in the allocating closure.
// self is an unowned capture to break the reference cycles between Usage -> ReallocateIfNeeded -> Closure -> Us...
lazy var costly: ReallocateIfNeeded<CostlyAllocatedObject> = ReallocateIfNeeded {
[unowned self] in
return CostlyAllocatedObject(self.isPrivate!, self.isStarred!, self.isUnread!)
}
}
let test = Usage()
// First Usage
test.isPrivate // -> true
test.isStarred // -> true
test.isUnread // -> true
test.costly.instance // (Re)-Allocating Costly
// Nothing changed
test.isPrivate = true // isPrivate: comparing new value (true) to old value (true)
test.costly.instance // Returning cached Costly
// Changes galore!
test.isPrivate = false // isPrivate: comparing new value (false) to old value (true)
test.isStarred = false // isStarred: comparing new value (false) to old value (true)
test.isUnread = false // isUnread: comparing new value (false) to old value (true)
test.costly.instance // (Re)-Allocating Costly
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment