Skip to content

Instantly share code, notes, and snippets.

@orgmir
Created November 1, 2018 01:40
Show Gist options
  • Save orgmir/37ea0b21495063645c081243b14291ee to your computer and use it in GitHub Desktop.
Save orgmir/37ea0b21495063645c081243b14291ee to your computer and use it in GitHub Desktop.
actual inline fun <R> sync(lock: Any, block: () -> R): R = synchronized(lock, block)
actual object Timber {
actual val forestList = mutableListOf<Tree>()
actual var forestArray: Array<Tree> = emptyArray()
}
import platform.objc.objc_sync_enter
import platform.objc.objc_sync_exit
actual inline fun <R> sync(lock: Any, block: () -> R): R {
try {
objc_sync_enter(lock)
return block()
} finally {
objc_sync_exit(lock)
}
}
@ThreadLocal
actual object Timber {
actual val forestList = mutableListOf<Tree>()
actual var forestArray: Array<Tree> = emptyArray()
}
// For fun, this is my sync implemntation
expect inline fun <R> sync(lock: Any, block: () -> R): R
// LR: This needs to be declared this way so we can add
// the @ThreadLocal anotation in native.
expect object Timber {
val forestList: MutableList<Tree>
var forestArray: Array<Tree>
}
// Everything is now declared has an extension!
val Timber.VERBOSE
get() = 2
val Timber.DE_BUG
get() = 3 // clash with #define DE_BUG in OBJ-C
val Timber.INFO
get() = 4
val Timber.WARNING
get() = 5
val Timber.ERROR
get() = 6
val Timber.ASSERT
get() = 7
val Timber.trees get() = forestArray.toList()
val Timber.size get() = forestArray.size
fun Timber.uprootAll() {
sync(forestList) {
forestList.clear()
forestArray = emptyArray()
}
}
fun Timber.uproot(tree: Tree) {
sync(forestList) {
require(forestList.remove(tree)) { "Cannot uproot tree which is not planted: $tree" }
forestArray = forestList.toTypedArray()
}
}
fun Timber.plant(tree: Tree) {
sync(forestList) {
forestList.add(tree)
forestArray = forestList.toTypedArray()
}
}
fun Timber.plant(vararg trees: Tree) {
sync(forestList) {
forestList.addAll(trees)
forestArray = forestList.toTypedArray()
}
}
fun Timber.plantAll(trees: Iterable<Tree>) {
sync(forestList) {
forestList.addAll(trees)
forestArray = forestList.toTypedArray()
}
}
fun Timber.isLoggable(priority: Int, tag: String? = null) = forestArray.any { it.isLoggable(priority, tag) }
fun Timber.log(priority: Int, tag: String?, throwable: Throwable?, message: String?) {
forestArray.forEach { it.log(priority, tag, throwable, message) }
}
/** Invoked only when [isLoggable] has returned true. */
@PublishedApi
internal fun Timber.rawLog(priority: Int, tag: String?, throwable: Throwable?, message: String?) {
forestArray.forEach { it.rawLog(priority, tag, throwable, message) }
}
fun Timber.tagged(tag: String): Tree {
val taggedTag = tag
return object : Tree() {
override fun isLoggable(priority: Int, tag: String?): Boolean {
return Timber.isLoggable(priority, tag ?: taggedTag)
}
override fun performLog(priority: Int, tag: String?, throwable: Throwable?, message: String?) {
Timber.log(priority, tag ?: taggedTag, throwable, message)
}
}
}
inline fun Timber.log(priority: Int, throwable: Throwable? = null, message: () -> String) {
if (isLoggable(priority, null)) {
rawLog(priority, null, throwable, message())
}
}
inline fun Timber.assert(throwable: Throwable? = null, message: () -> String) {
log(Timber.ASSERT, throwable, message)
}
inline fun Timber.error(throwable: Throwable? = null, message: () -> String) {
log(Timber.ERROR, throwable, message)
}
inline fun Timber.warn(throwable: Throwable? = null, message: () -> String) {
log(Timber.WARNING, throwable, message)
}
inline fun Timber.info(throwable: Throwable? = null, message: () -> String) {
log(Timber.INFO, throwable, message)
}
inline fun Timber.debug(throwable: Throwable? = null, message: () -> String) {
log(Timber.DE_BUG, throwable, message)
}
inline fun Timber.verbose(throwable: Throwable? = null, message: () -> String) {
log(Timber.VERBOSE, throwable, message)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment