| /* | |
| * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license | |
| * that can be found in the LICENSE file. | |
| */ | |
| @file:OptIn(ObsoleteWorkersApi::class) | |
| package runtime.basic.initializers6 | |
| import kotlin.test.* | |
| import kotlin.concurrent.AtomicInt | |
| import kotlin.concurrent.* | |
| import kotlin.native.concurrent.* | |
| val aWorkerId = AtomicInt(0) | |
| val bWorkersCount = 3 | |
| val aWorkerUnlocker = AtomicInt(0) | |
| val bWorkerUnlocker = AtomicInt(0) | |
| object A { | |
| init { | |
| // Must be called by aWorker only. | |
| assertEquals(aWorkerId.value, Worker.current.id) | |
| // Only allow b workers to run, when a worker has started initialization. | |
| bWorkerUnlocker.incrementAndGet() | |
| // Only proceed with initialization, when all b workers have started executing. | |
| while (aWorkerUnlocker.value < bWorkersCount) {} | |
| // And now wait a bit, to increase probability of races. | |
| Worker.current.park(100 * 1000L) | |
| } | |
| val a = produceA() | |
| val b = produceB() | |
| } | |
| fun produceA(): String { | |
| // Must've been called by aWorker only. | |
| assertEquals(aWorkerId.value, Worker.current.id) | |
| return "A" | |
| } | |
| fun produceB(): String { | |
| // Must've been called by aWorker only. | |
| assertEquals(aWorkerId.value, Worker.current.id) | |
| // Also check that it's ok to get A.a while initializing A.b. | |
| return "B+${A.a}" | |
| } | |
| fun box(): String { | |
| val aWorker = Worker.start() | |
| aWorkerId.value = aWorker.id | |
| val bWorkers = Array(bWorkersCount, { _ -> Worker.start() }) | |
| val aFuture = aWorker.execute(TransferMode.SAFE, {}, { | |
| A.b | |
| }) | |
| val bFutures = Array(bWorkers.size, { | |
| bWorkers[it].execute(TransferMode.SAFE, {}, { | |
| // Wait until A has started to initialize. | |
| while (bWorkerUnlocker.value < 1) {} | |
| // Now allow A initialization to continue. | |
| aWorkerUnlocker.incrementAndGet() | |
| // And this should not've tried to init A itself. | |
| A.a + A.b | |
| }) | |
| }) | |
| for (future in bFutures) { | |
| assertEquals("AB+A", future.result) | |
| } | |
| assertEquals("B+A", aFuture.result) | |
| for (worker in bWorkers) { | |
| worker.requestTermination().result | |
| } | |
| aWorker.requestTermination().result | |
| return "OK" | |
| } |