Skip to content

Commit 66298a5

Browse files
authored
Add a command line option & directive for enabling/disabling Scala Native multithreading (#3011)
1 parent 63b4748 commit 66298a5

File tree

9 files changed

+131
-3
lines changed

9 files changed

+131
-3
lines changed

modules/build/src/test/scala/scala/build/tests/ScalaNativeUsingDirectiveTests.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,4 +236,17 @@ class ScalaNativeUsingDirectiveTests extends TestUtil.ScalaCliBuildSuite {
236236
)
237237
}
238238
}
239+
240+
for { multithreadingDirective <- Seq("`native-multithreading`", "nativeMultithreading") }
241+
test(s"ScalaNativeOptions for $multithreadingDirective") {
242+
val inputs = TestInputs(
243+
os.rel / "p.sc" ->
244+
s"""//> using $multithreadingDirective
245+
|def foo() = println("hello foo")
246+
|""".stripMargin
247+
)
248+
inputs.withLoadedBuild(buildOptions, buildThreads, bloopConfig) { (_, _, maybeBuild) =>
249+
assert(maybeBuild.options.scalaNativeOptions.multithreading.get)
250+
}
251+
}
239252
}

modules/cli/src/main/scala/scala/cli/commands/shared/ScalaNativeOptions.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,12 @@ final case class ScalaNativeOptions(
7070
@Group(HelpGroup.ScalaNative.toString)
7171
@HelpMessage("Embed resources into the Scala Native binary (can be read with the Java resources API)")
7272
@Tag(tags.should)
73-
embedResources: Option[Boolean] = None
73+
embedResources: Option[Boolean] = None,
74+
75+
@Group(HelpGroup.ScalaNative.toString)
76+
@HelpMessage("Enable/disable Scala Native multithreading support")
77+
@Tag(tags.should)
78+
nativeMultithreading: Option[Boolean] = None
7479

7580
)
7681
// format: on

modules/cli/src/main/scala/scala/cli/commands/shared/SharedOptions.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ final case class SharedOptions(
285285
compileDefaults = nativeCompileDefaults,
286286
embedResources = embedResources,
287287
buildTargetStr = nativeTarget,
288+
multithreading = nativeMultithreading,
288289
maxDefaultNativeVersions = maxDefaultScalaNativeVersions
289290
)
290291
}

modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalaNative.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ final case class ScalaNative(
4646
nativeClangPP: Option[String] = None,
4747
nativeEmbedResources: Option[Boolean] = None,
4848
nativeTarget: Option[String] = None,
49+
nativeMultithreading: Option[Boolean] = None
4950
) extends HasBuildOptions {
5051
// format: on
5152
def buildOptions: Either[BuildException, BuildOptions] = {
@@ -59,7 +60,8 @@ final case class ScalaNative(
5960
clang = nativeClang,
6061
clangpp = nativeClangPP,
6162
embedResources = nativeEmbedResources,
62-
buildTargetStr = nativeTarget
63+
buildTargetStr = nativeTarget,
64+
multithreading = nativeMultithreading
6365
)
6466
val buildOpt = BuildOptions(scalaNativeOptions = nativeOptions)
6567
Right(buildOpt)

modules/integration/src/test/scala/scala/cli/integration/RunScalaNativeTestDefinitions.scala

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,4 +401,60 @@ trait RunScalaNativeTestDefinitions { _: RunTestDefinitions =>
401401
}
402402
}
403403
}
404+
405+
for {
406+
expectedMultithreadingState <- Seq(true, false)
407+
// multithreading should be enabled by Scala Native by default
408+
setExplicitly <- if (expectedMultithreadingState) Seq(true, false) else Seq(true)
409+
useDirective <- if (setExplicitly) Seq(true, false) else Seq(false)
410+
directive =
411+
if (useDirective && setExplicitly)
412+
s"//> using nativeMultithreading $expectedMultithreadingState"
413+
else ""
414+
cliOptions =
415+
if (!useDirective && setExplicitly)
416+
Seq(s"--native-multithreading=$expectedMultithreadingState")
417+
else Nil
418+
testDescriptionString = useDirective -> setExplicitly match {
419+
case (_, false) => "(implicitly)"
420+
case (true, true) => "with directive"
421+
case (false, true) => "with command line option"
422+
}
423+
}
424+
test(
425+
s"Scala Native multithreading set to $expectedMultithreadingState $testDescriptionString"
426+
) {
427+
val fileName = "multithreading.sc"
428+
val expectedOutput = "42"
429+
val threadSleep = "100"
430+
val threadAwait = "2.seconds"
431+
val inputs = TestInputs(
432+
os.rel / fileName ->
433+
s"""$directive
434+
|import scala.concurrent._
435+
|import scala.concurrent.duration._
436+
|import ExecutionContext.Implicits.global
437+
|val promise = Promise[Int]()
438+
|val thread = new Thread(new Runnable {
439+
| def run(): Unit = {
440+
| Thread.sleep($threadSleep)
441+
| promise.success($expectedOutput)
442+
| }
443+
| })
444+
|thread.start()
445+
|val result = Await.result(promise.future, $threadAwait)
446+
|println(result)
447+
|""".stripMargin
448+
)
449+
inputs.fromRoot { root =>
450+
val r = os.proc(TestUtil.cli, extraOptions, fileName, "--native", cliOptions)
451+
.call(cwd = root, stderr = os.Pipe, check = expectedMultithreadingState)
452+
if (!expectedMultithreadingState) expect(r.exitCode == 1)
453+
else {
454+
expect(r.exitCode == 0)
455+
expect(r.out.trim() == expectedOutput)
456+
}
457+
expect(r.err.trim().contains(s"multithreadingEnabled=$expectedMultithreadingState"))
458+
}
459+
}
404460
}

modules/options/src/main/scala/scala/build/options/ScalaNativeOptions.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ final case class ScalaNativeOptions(
4040
compileDefaults: Option[Boolean] = None,
4141
embedResources: Option[Boolean] = None,
4242
buildTargetStr: Option[String] = None,
43+
multithreading: Option[Boolean] = None,
4344
maxDefaultNativeVersions: List[(String, String)] = Nil
4445
) {
4546

@@ -122,6 +123,9 @@ final case class ScalaNativeOptions(
122123
}
123124
else Nil
124125

126+
private def multithreadingCliOption(): List[String] =
127+
multithreading.toList.flatMap(m => List("--multithreading", m.toString))
128+
125129
def platformSuffix: String =
126130
"native" + ScalaVersion.nativeBinary(finalVersion).getOrElse(finalVersion)
127131

@@ -174,7 +178,8 @@ final case class ScalaNativeOptions(
174178
linkingCliOptions() ++
175179
compileCliOptions() ++
176180
resourcesCliOptions(resourcesExist) ++
177-
targetCliOption()
181+
targetCliOption() ++
182+
multithreadingCliOption()
178183

179184
}
180185

website/docs/reference/cli-options.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,10 @@ Build target type
13961396

13971397
Embed resources into the Scala Native binary (can be read with the Java resources API)
13981398

1399+
### `--native-multithreading`
1400+
1401+
Enable/disable Scala Native multithreading support
1402+
13991403
## Scalac options
14001404

14011405
Available in commands:

website/docs/reference/scala-command/cli-options.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,12 @@ Build target type
900900

901901
Embed resources into the Scala Native binary (can be read with the Java resources API)
902902

903+
### `--native-multithreading`
904+
905+
`SHOULD have` per Scala Runner specification
906+
907+
Enable/disable Scala Native multithreading support
908+
903909
## Scalac options
904910

905911
Available in commands:

website/docs/reference/scala-command/runner-specification.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ Build target type
204204

205205
Embed resources into the Scala Native binary (can be read with the Java resources API)
206206

207+
**--native-multithreading**
208+
209+
Enable/disable Scala Native multithreading support
210+
207211
**--repository**
208212

209213
Add repositories for dependency resolution.
@@ -967,6 +971,10 @@ Build target type
967971

968972
Embed resources into the Scala Native binary (can be read with the Java resources API)
969973

974+
**--native-multithreading**
975+
976+
Enable/disable Scala Native multithreading support
977+
970978
**--repository**
971979

972980
Add repositories for dependency resolution.
@@ -1532,6 +1540,10 @@ Build target type
15321540

15331541
Embed resources into the Scala Native binary (can be read with the Java resources API)
15341542

1543+
**--native-multithreading**
1544+
1545+
Enable/disable Scala Native multithreading support
1546+
15351547
**--repository**
15361548

15371549
Add repositories for dependency resolution.
@@ -2129,6 +2141,10 @@ Build target type
21292141

21302142
Embed resources into the Scala Native binary (can be read with the Java resources API)
21312143

2144+
**--native-multithreading**
2145+
2146+
Enable/disable Scala Native multithreading support
2147+
21322148
**--repository**
21332149

21342150
Add repositories for dependency resolution.
@@ -2739,6 +2755,10 @@ Build target type
27392755

27402756
Embed resources into the Scala Native binary (can be read with the Java resources API)
27412757

2758+
**--native-multithreading**
2759+
2760+
Enable/disable Scala Native multithreading support
2761+
27422762
**--repository**
27432763

27442764
Add repositories for dependency resolution.
@@ -3325,6 +3345,10 @@ Build target type
33253345

33263346
Embed resources into the Scala Native binary (can be read with the Java resources API)
33273347

3348+
**--native-multithreading**
3349+
3350+
Enable/disable Scala Native multithreading support
3351+
33283352
**--repository**
33293353

33303354
Add repositories for dependency resolution.
@@ -3948,6 +3972,10 @@ Build target type
39483972

39493973
Embed resources into the Scala Native binary (can be read with the Java resources API)
39503974

3975+
**--native-multithreading**
3976+
3977+
Enable/disable Scala Native multithreading support
3978+
39513979
**--repository**
39523980

39533981
Add repositories for dependency resolution.
@@ -4622,6 +4650,10 @@ Build target type
46224650

46234651
Embed resources into the Scala Native binary (can be read with the Java resources API)
46244652

4653+
**--native-multithreading**
4654+
4655+
Enable/disable Scala Native multithreading support
4656+
46254657
**--repository**
46264658

46274659
Add repositories for dependency resolution.
@@ -5537,6 +5569,10 @@ Build target type
55375569

55385570
Embed resources into the Scala Native binary (can be read with the Java resources API)
55395571

5572+
**--native-multithreading**
5573+
5574+
Enable/disable Scala Native multithreading support
5575+
55405576
**--repository**
55415577

55425578
Add repositories for dependency resolution.

0 commit comments

Comments
 (0)