[K/N] Deprecated freezing ^KT-50541
Starting with 1.7.20 freezing is deprecated. See https://github.com/JetBrains/kotlin/blob/master/kotlin-native/NEW_MM.md#freezing-deprecation for details. Merge-request: KT-MR-6399 Merged-by: Alexander Shabalin <Alexander.Shabalin@jetbrains.com>
This commit is contained in:
committed by
Space
parent
b482b0e86d
commit
29f3445721
@@ -20,9 +20,9 @@ data class SharedDataMember(val double: Double)
|
||||
|
||||
data class SharedData(val string: String, val int: Int, val member: SharedDataMember)
|
||||
|
||||
// Here we access the same shared frozen Kotlin object from multiple threads.
|
||||
// Here we access the same shared Kotlin object from multiple threads.
|
||||
val globalObject: SharedData?
|
||||
get() = sharedData.frozenKotlinObject?.asStableRef<SharedData>()?.get()
|
||||
get() = sharedData.kotlinObject?.asStableRef<SharedData>()?.get()
|
||||
|
||||
fun dumpShared(prefix: String) {
|
||||
println("""
|
||||
@@ -39,16 +39,11 @@ fun main() {
|
||||
sharedData.f = 0.5f
|
||||
sharedData.string = "Hello Kotlin!".cstr.getPointer(arena)
|
||||
|
||||
// Here we create detached mutable object, which could be later reattached by another thread.
|
||||
sharedData.kotlinObject = DetachedObjectGraph {
|
||||
SharedData("A string", 42, SharedDataMember(2.39))
|
||||
}.asCPointer()
|
||||
|
||||
// Here we create shared frozen object reference,
|
||||
val stableRef = StableRef.create(SharedData("Shared", 239, SharedDataMember(2.71)).freeze())
|
||||
sharedData.frozenKotlinObject = stableRef.asCPointer()
|
||||
// Here we create shared object reference,
|
||||
val stableRef = StableRef.create(SharedData("Shared", 239, SharedDataMember(2.71)))
|
||||
sharedData.kotlinObject = stableRef.asCPointer()
|
||||
dumpShared("thread1")
|
||||
println("frozen is $globalObject")
|
||||
println("shared is $globalObject")
|
||||
|
||||
// Start a new thread, that sees the variable.
|
||||
// memScoped is needed to pass thread's local address to pthread_create().
|
||||
@@ -57,12 +52,12 @@ fun main() {
|
||||
pthread_create(thread.ptr, null, staticCFunction { argC ->
|
||||
initRuntimeIfNeeded()
|
||||
dumpShared("thread2")
|
||||
val kotlinObject = DetachedObjectGraph<SharedData>(sharedData.kotlinObject).attach()
|
||||
val arg = DetachedObjectGraph<SharedDataMember>(argC).attach()
|
||||
println("thread arg is $arg Kotlin object is $kotlinObject frozen is $globalObject")
|
||||
val arg = argC!!.asStableRef<SharedDataMember>()
|
||||
println("thread arg is ${arg.get()} shared is $globalObject")
|
||||
arg.dispose()
|
||||
// Workaround for compiler issue.
|
||||
null as COpaquePointer?
|
||||
}, DetachedObjectGraph { SharedDataMember(3.14)}.asCPointer() ).ensureUnixCallResult("pthread_create")
|
||||
}, StableRef.create(SharedDataMember(3.14)).asCPointer() ).ensureUnixCallResult("pthread_create")
|
||||
pthread_join(thread.value, null).ensureUnixCallResult("pthread_join")
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ typedef struct {
|
||||
float f;
|
||||
char* string;
|
||||
void* kotlinObject;
|
||||
void* frozenKotlinObject;
|
||||
} SharedDataStruct;
|
||||
|
||||
SharedDataStruct sharedData;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package sample.objc
|
||||
|
||||
import kotlinx.cinterop.staticCFunction
|
||||
import kotlinx.cinterop.*
|
||||
import platform.Foundation.NSOperationQueue
|
||||
import platform.Foundation.NSThread
|
||||
import platform.darwin.dispatch_async_f
|
||||
@@ -10,11 +10,12 @@ import kotlin.native.concurrent.*
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
inline fun <reified T> executeAsync(queue: NSOperationQueue, crossinline producerConsumer: () -> Pair<T, (T) -> Unit>) {
|
||||
dispatch_async_f(queue.underlyingQueue, DetachedObjectGraph {
|
||||
dispatch_async_f(queue.underlyingQueue, StableRef.create(
|
||||
producerConsumer()
|
||||
}.asCPointer(), staticCFunction { it ->
|
||||
val result = DetachedObjectGraph<Pair<T, (T) -> Unit>>(it).attach()
|
||||
result.second(result.first)
|
||||
).asCPointer(), staticCFunction { it ->
|
||||
val result = it!!.asStableRef<Pair<T, (T) -> Unit>>()
|
||||
result.get().second(result.get().first)
|
||||
result.dispose()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -60,8 +61,7 @@ object Continuator {
|
||||
|
||||
fun wrap(operation: () -> Unit, after: () -> Unit): () -> Unit {
|
||||
assert(NSThread.isMainThread())
|
||||
assert(operation.isFrozen)
|
||||
val id = Any().freeze()
|
||||
val id = Any()
|
||||
map[id] = Pair(0, after)
|
||||
return {
|
||||
initRuntimeIfNeeded()
|
||||
@@ -69,13 +69,12 @@ object Continuator {
|
||||
executeAsync(NSOperationQueue.mainQueue) {
|
||||
Pair(id, { id: Any -> Continuator.execute(id) })
|
||||
}
|
||||
}.freeze()
|
||||
}
|
||||
}
|
||||
|
||||
fun <P> wrap(operation: () -> P, block: (P) -> Unit): () -> Unit {
|
||||
assert(NSThread.isMainThread())
|
||||
assert(operation.isFrozen)
|
||||
val id = Any().freeze()
|
||||
val id = Any()
|
||||
map[id] = Pair(1, block)
|
||||
return {
|
||||
initRuntimeIfNeeded()
|
||||
@@ -85,7 +84,7 @@ object Continuator {
|
||||
Continuator.execute(it.first, it.second)
|
||||
})
|
||||
}
|
||||
}.freeze()
|
||||
}
|
||||
}
|
||||
|
||||
fun execute(id: Any) {
|
||||
|
||||
@@ -18,14 +18,8 @@ import kotlin.test.assertNotNull
|
||||
|
||||
data class QueryResult(val json: Map<String, *>?, val error: String?)
|
||||
|
||||
private fun MutableData.asNSData() = this.withPointerLocked { it, size ->
|
||||
val result = NSMutableData.create(length = size.convert())!!
|
||||
memcpy(result.mutableBytes, it, size.convert())
|
||||
result
|
||||
}
|
||||
|
||||
private fun MutableData.asJSON(): Map<String, *>? =
|
||||
NSJSONSerialization.JSONObjectWithData(this.asNSData(), 0, null) as? Map<String, *>
|
||||
private val NSData.json: Map<String, *>?
|
||||
get() = NSJSONSerialization.JSONObjectWithData(this, 0, null) as? Map<String, *>
|
||||
|
||||
fun main() {
|
||||
autoreleasepool {
|
||||
@@ -60,7 +54,7 @@ class Controller : NSObject() {
|
||||
// Here we call continuator service to ensure we can access mutable state from continuation.
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND.convert(), 0),
|
||||
Continuator.wrap({ println("In queue ${dispatch_get_current_queue()}")}.freeze()) {
|
||||
Continuator.wrap({ println("In queue ${dispatch_get_current_queue()}")}) {
|
||||
println("After in queue ${dispatch_get_current_queue()}: $index")
|
||||
})
|
||||
|
||||
@@ -88,14 +82,10 @@ class Controller : NSObject() {
|
||||
|
||||
class HttpDelegate: NSObject(), NSURLSessionDataDelegateProtocol {
|
||||
private val asyncQueue = NSOperationQueue()
|
||||
private val receivedData = MutableData()
|
||||
|
||||
init {
|
||||
freeze()
|
||||
}
|
||||
private var receivedData: NSData? = null
|
||||
|
||||
fun fetchUrl(url: String) {
|
||||
receivedData.reset()
|
||||
receivedData = null
|
||||
val session = NSURLSession.sessionWithConfiguration(
|
||||
NSURLSessionConfiguration.defaultSessionConfiguration(),
|
||||
this,
|
||||
@@ -106,7 +96,7 @@ class Controller : NSObject() {
|
||||
|
||||
override fun URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData: NSData) {
|
||||
initRuntimeIfNeeded()
|
||||
receivedData.append(didReceiveData.bytes, didReceiveData.length.convert())
|
||||
receivedData = didReceiveData
|
||||
}
|
||||
|
||||
override fun URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError: NSError?) {
|
||||
@@ -117,7 +107,7 @@ class Controller : NSObject() {
|
||||
Pair(when {
|
||||
response == null -> QueryResult(null, didCompleteWithError?.localizedDescription)
|
||||
response.statusCode.toInt() != 200 -> QueryResult(null, "${response.statusCode.toInt()})")
|
||||
else -> QueryResult(receivedData.asJSON(), null)
|
||||
else -> QueryResult(receivedData?.json, null)
|
||||
}, { result: QueryResult ->
|
||||
appDelegate.contentText.string = result.json?.toString() ?: "Error: ${result.error}"
|
||||
appDelegate.canClick = true
|
||||
|
||||
Reference in New Issue
Block a user