Skip to content

Commit d04ffc6

Browse files
dovchinnikovintellij-monorepo-bot
authored andcommitted
update subtask function to work around withContext behaviour
See Kotlin/kotlinx.coroutines#3411 See Kotlin/kotlinx.coroutines#3414 GitOrigin-RevId: 234f21de1899b48425f97193ca63769246b54173
1 parent d72aa6e commit d04ffc6

File tree

2 files changed

+29
-27
lines changed

2 files changed

+29
-27
lines changed

platform/diagnostic/src/tracer.kt

+22-20
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,29 @@ import kotlin.coroutines.coroutineContext
2828
fun rootTask(): CoroutineContext = MeasureCoroutineTime
2929

3030
/**
31-
* This function forces child activity for [withContext] blocks,
32-
* which don't fork [CopyableThreadContextElement] under normal conditions.
33-
*
34-
* Example:
35-
* ```
36-
* launch(CoroutineName("init stuff")) {
37-
* ...
38-
* withContext(subtask("init stuff step 1") {
39-
* ...
40-
* }
41-
* ...
42-
* withContext(Dispatchers.EDT + subtask("init stuff step 2") {
43-
* ...
44-
* }
45-
* ...
46-
* }
31+
* This function is designed to be used instead of `withContext(CoroutineName("subtask")) { ... }`.
4732
*/
48-
suspend fun subtask(name: String): CoroutineContext {
49-
val measurer = coroutineContext[CoroutineTimeMeasurerKey]
50-
val childMeasurer = measurer?.copyForChild() ?: EmptyCoroutineContext
51-
return CoroutineName(name) + childMeasurer
33+
suspend fun <X> subtask(
34+
name: String,
35+
context: CoroutineContext = EmptyCoroutineContext,
36+
action: suspend CoroutineScope.() -> X,
37+
): X {
38+
val namedContext = context + CoroutineName(name)
39+
if (coroutineContext[CoroutineTimeMeasurerKey] == null) {
40+
return withContext(namedContext, action)
41+
}
42+
return coroutineScope {
43+
@OptIn(ExperimentalStdlibApi::class)
44+
val start = if (coroutineContext[CoroutineDispatcher] == context[CoroutineDispatcher]) {
45+
// mimic withContext behaviour with its UndispatchedCoroutine
46+
CoroutineStart.UNDISPATCHED
47+
}
48+
else {
49+
CoroutineStart.DEFAULT
50+
}
51+
// async forces the framework to call CopyableThreadContextElement#copyForChild
52+
async(namedContext, start, action).await()
53+
}
5254
}
5355

5456
private val noActivity: Activity = object : Activity {

platform/platform-impl/src/com/intellij/idea/StartupUtil.kt

+7-7
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ fun start(args: Array<String>) {
176176
else {
177177
val euaDocument = euaDocumentDeferred.await()
178178
val baseLaF = initUiJob.await()
179-
withContext(subtask("show eua")) {
179+
subtask("show eua") {
180180
showEuaIfNeeded(euaDocument, baseLaF)
181181
}
182182
}
@@ -187,7 +187,7 @@ fun start(args: Array<String>) {
187187
configImportNeededDeferred.join()
188188

189189
val (configPath, systemPath) = pathDeferred.await()
190-
withContext(subtask("system dirs checking")) {
190+
subtask("system dirs checking") {
191191
if (!checkSystemDirs(configPath, systemPath)) {
192192
exitProcess(AppExitCodes.DIR_CHECK_FAILED)
193193
}
@@ -268,11 +268,11 @@ fun start(args: Array<String>) {
268268
// this must happen after locking system dirs
269269
val log = logDeferred.await()
270270

271-
withContext(subtask("system libs setup")) {
271+
subtask("system libs setup") {
272272
setupSystemLibraries()
273273
}
274274

275-
withContext(subtask("system libs loading") + Dispatchers.IO) {
275+
subtask("system libs loading", Dispatchers.IO) {
276276
JnaLoader.load(log)
277277
if (SystemInfoRt.isWindows) {
278278
IdeaWin32.isAvailable()
@@ -289,7 +289,7 @@ fun start(args: Array<String>) {
289289
launch {
290290
initUiJob.join()
291291

292-
withContext(subtask("mac app init")) {
292+
subtask("mac app init") {
293293
MacOSApplicationProvider.initApplication(log)
294294
}
295295
}
@@ -310,7 +310,7 @@ fun start(args: Array<String>) {
310310

311311
val telemetryInitJob = launch(asyncDispatcher) {
312312
appInfoDeferred.join()
313-
withContext(subtask("opentelemetry configuration")) {
313+
subtask("opentelemetry configuration") {
314314
TraceManager.init()
315315
}
316316
}
@@ -873,7 +873,7 @@ private fun CoroutineScope.lockSystemDirs(checkConfig: Boolean,
873873

874874
return async(Dispatchers.IO) {
875875
val (configPath, systemPath) = pathDeferred.await()
876-
withContext(subtask("system dirs locking")) {
876+
subtask("system dirs locking") {
877877
// this check must be performed before system directories are locked
878878
val importNeeded = checkConfig &&
879879
(!Files.exists(configPath) || Files.exists(configPath.resolve(ConfigImportHelper.CUSTOM_MARKER_FILE_NAME)))

0 commit comments

Comments
 (0)