Add defer support to memScope

This commit is contained in:
Svyatoslav Scherbina
2017-09-19 11:53:27 +03:00
committed by SvyatoslavScherbina
parent 9609a10e09
commit 2217be4003
@@ -36,12 +36,41 @@ object nativeHeap : NativeFreeablePlacement {
override fun free(mem: NativePtr) = nativeMemUtils.free(mem) override fun free(mem: NativePtr) = nativeMemUtils.free(mem)
} }
private typealias Deferred = () -> Unit
open class DeferScope {
@PublishedApi
internal var topDeferred: Deferred? = null
internal fun executeAllDeferred() {
topDeferred?.let {
it.invoke()
topDeferred = null
}
}
inline fun defer(crossinline block: () -> Unit) {
val currentTop = topDeferred
topDeferred = {
try {
block()
} finally {
// TODO: it is possible to implement chaining without recursion,
// but it would require using an anonymous object here
// which is not yet supported in Kotlin Native inliner.
currentTop?.invoke()
}
}
}
}
// TODO: implement optimally // TODO: implement optimally
class Arena(private val parent: NativeFreeablePlacement = nativeHeap) : NativePlacement { open class ArenaBase(private val parent: NativeFreeablePlacement = nativeHeap) : NativePlacement, DeferScope() {
private val allocatedChunks = ArrayList<NativePointed>() private val allocatedChunks = ArrayList<NativePointed>()
override fun alloc(size: Long, align: Int): NativePointed { final override fun alloc(size: Long, align: Int): NativePointed {
val res = parent.alloc(size, align) val res = parent.alloc(size, align)
try { try {
allocatedChunks.add(res) allocatedChunks.add(res)
@@ -52,7 +81,10 @@ class Arena(private val parent: NativeFreeablePlacement = nativeHeap) : NativePl
} }
} }
fun clear() { @PublishedApi
internal fun clearImpl() {
this.executeAllDeferred()
allocatedChunks.forEach { allocatedChunks.forEach {
parent.free(it) parent.free(it)
} }
@@ -62,6 +94,10 @@ class Arena(private val parent: NativeFreeablePlacement = nativeHeap) : NativePl
} }
class Arena(parent: NativeFreeablePlacement = nativeHeap) : ArenaBase(parent) {
fun clear() = this.clearImpl()
}
/** /**
* Allocates variable of given type. * Allocates variable of given type.
* *
@@ -355,18 +391,14 @@ fun CPointer<ByteVar>.toKString(): String {
return decodeFromUtf8(bytes) return decodeFromUtf8(bytes)
} }
class MemScope : NativePlacement { class MemScope : ArenaBase() {
private val arena = Arena() val memScope: MemScope
override fun alloc(size: Long, align: Int) = arena.alloc(size, align)
fun clear() = arena.clear()
val memScope: NativePlacement
get() = this get() = this
} }
// TODO: consider renaming `memScoped` because it now supports `defer`.
/** /**
* Runs given [block] providing allocation of memory * Runs given [block] providing allocation of memory
* which will be automatically disposed at the end of this scope. * which will be automatically disposed at the end of this scope.
@@ -376,7 +408,7 @@ inline fun <R> memScoped(block: MemScope.()->R): R {
try { try {
return memScope.block() return memScope.block()
} finally { } finally {
memScope.clear() memScope.clearImpl()
} }
} }