Skip to content

Instantly share code, notes, and snippets.

@JadenGeller
Created April 6, 2024 02:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JadenGeller/8115cd8058be4dd007e026de68264dcd to your computer and use it in GitHub Desktop.
Save JadenGeller/8115cd8058be4dd007e026de68264dcd to your computer and use it in GitHub Desktop.
struct ResourceManager {
#if DEBUG
let ticket: Int = .random(in: 0..<Int.max)
#endif
private var retainCount: [Int]
init(capacity: Int) {
self.retainCount = .init(repeating: 0, count: capacity)
}
struct Handle: ~Copyable {
#if DEBUG
let ticket: Int
#endif
fileprivate(set) var offset: Int
fileprivate consuming func forget() {
discard self
}
deinit {
assertionFailure("resource leak")
}
}
#if DEBUG
func checkTicket(of handle: borrowing Handle) {
assert(handle.ticket == ticket, "incompatible handle")
}
#endif
func forge(_ offset: Int) -> Handle {
#if DEBUG
.init(ticket: ticket, offset: offset)
#else
.init(offset: offset)
#endif
}
mutating func allocate() -> Handle {
for case (let offset, 0) in retainCount.enumerated() {
retainCount[offset] += 1
return forge(offset)
}
fatalError("allocation failure")
}
mutating func retaining(_ handle: borrowing Handle) -> Handle {
#if DEBUG
checkTicket(of: handle)
#endif
retainCount[handle.offset] += 1
return forge(handle.offset)
}
mutating func release(_ handle: consuming Handle) {
#if DEBUG
checkTicket(of: handle)
#endif
retainCount[handle.offset] -= 1
assert(retainCount[handle.offset] >= 0)
handle.forget()
}
mutating func swap(_ existing: inout Handle, with replacement: consuming Handle) -> Handle {
#if DEBUG
checkTicket(of: existing)
checkTicket(of: replacement)
#endif
(existing.offset, replacement.offset) = (replacement.offset, existing.offset)
return replacement
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment