Skip to content

Commit e0ea928

Browse files
committed
Swap shared vars for AtomicReferences
1 parent 7323222 commit e0ea928

File tree

1 file changed

+26
-18
lines changed
  • modules/cli/src/main/scala/scala/cli/commands/run

1 file changed

+26
-18
lines changed

modules/cli/src/main/scala/scala/cli/commands/run/Run.scala

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import caseapp.core.help.HelpFormat
77
import java.io.File
88
import java.util.Locale
99
import java.util.concurrent.CompletableFuture
10+
import java.util.concurrent.atomic.AtomicReference
1011

1112
import scala.build.EitherCps.{either, value}
1213
import scala.build.*
@@ -229,18 +230,18 @@ object Run extends ScalaCommand[RunOptions] with BuildCommandHelpers {
229230
/** A handle to the Runner process, used to kill the process if it's still alive when a change
230231
* occured and restarts are allowed or to wait for it if restarts are not allowed
231232
*/
232-
var processOpt = Option.empty[(Process, CompletableFuture[_])]
233+
val processOpt = AtomicReference(Option.empty[(Process, CompletableFuture[_])])
233234

234235
/** shouldReadInput controls whether [[WatchUtil.waitForCtrlC]](that's keeping the main thread
235236
* alive) should try to read StdIn or just call wait()
236237
*/
237-
var shouldReadInput = false
238+
val shouldReadInput = AtomicReference(false)
238239

239-
/** a handle to the main thread to interrupt its operations when:
240+
/** A handle to the main thread to interrupt its operations when:
240241
* - it's blocked on reading StdIn, and it's no longer required
241242
* - it's waiting and should start reading StdIn
242243
*/
243-
var mainThreadOpt = Option.empty[Thread]
244+
val mainThreadOpt = AtomicReference(Option.empty[Thread])
244245

245246
val watcher = Build.watch(
246247
inputs,
@@ -253,22 +254,22 @@ object Run extends ScalaCommand[RunOptions] with BuildCommandHelpers {
253254
partial = None,
254255
actionableDiagnostics = actionableDiagnostics,
255256
postAction = () =>
256-
if (processOpt.exists(_._1.isAlive()))
257+
if (processOpt.get().exists(_._1.isAlive()))
257258
WatchUtil.printWatchWhileRunningMessage()
258259
else
259260
WatchUtil.printWatchMessage()
260261
) { res =>
261-
for ((process, onExitProcess) <- processOpt) {
262+
for ((process, onExitProcess) <- processOpt.get()) {
262263
onExitProcess.cancel(true)
263264
ProcUtil.interruptProcess(process, logger)
264265
}
265266
res.orReport(logger).map(_.main).foreach {
266267
case s: Build.Successful =>
267-
for ((proc, _) <- processOpt if proc.isAlive)
268+
for ((proc, _) <- processOpt.get() if proc.isAlive)
268269
// If the process doesn't exit, send SIGKILL
269270
ProcUtil.forceKillProcess(proc, logger)
270-
shouldReadInput = false
271-
mainThreadOpt.foreach(_.interrupt())
271+
shouldReadInput.set(false)
272+
mainThreadOpt.get().foreach(_.interrupt())
272273
val maybeProcess = maybeRun(
273274
s,
274275
allowTerminate = false,
@@ -282,29 +283,36 @@ object Run extends ScalaCommand[RunOptions] with BuildCommandHelpers {
282283
case (proc, onExit) =>
283284
if (options.sharedRun.watch.restart)
284285
onExit.thenApply { _ =>
285-
shouldReadInput = true
286-
mainThreadOpt.foreach(_.interrupt())
286+
shouldReadInput.set(true)
287+
mainThreadOpt.get().foreach(_.interrupt())
287288
}
288289
(proc, onExit)
289290
}
290291
s.copyOutput(options.shared)
291292
if (options.sharedRun.watch.restart)
292-
processOpt = maybeProcess
293+
processOpt.set(maybeProcess)
293294
else {
294295
for ((proc, onExit) <- maybeProcess)
295296
ProcUtil.waitForProcess(proc, onExit)
296-
shouldReadInput = true
297-
mainThreadOpt.foreach(_.interrupt())
297+
shouldReadInput.set(true)
298+
mainThreadOpt.get().foreach(_.interrupt())
298299
}
299300
case _: Build.Failed =>
300301
System.err.println("Compilation failed")
301302
}
302303
}
303-
mainThreadOpt = Some(Thread.currentThread())
304-
305-
try WatchUtil.waitForCtrlC(() => watcher.schedule(), () => shouldReadInput)
304+
mainThreadOpt.set(Some(Thread.currentThread()))
305+
306+
try
307+
WatchUtil.waitForCtrlC(
308+
{ () =>
309+
watcher.schedule()
310+
shouldReadInput.set(false)
311+
},
312+
() => shouldReadInput.get()
313+
)
306314
finally {
307-
mainThreadOpt = None
315+
mainThreadOpt.set(None)
308316
watcher.dispose()
309317
}
310318
}

0 commit comments

Comments
 (0)