@@ -705,9 +705,10 @@ catch ex
705
705
end
706
706
707
707
@testset " @spawn interpolation" begin
708
- # Issue #30896: evaluating argumentss immediately
708
+ # Issue #30896: evaluating arguments immediately
709
709
begin
710
710
outs = zeros (5 )
711
+ # Use interpolation to fill outs with the values of `i`
711
712
@sync begin
712
713
local i = 1
713
714
while i <= 5
@@ -718,40 +719,50 @@ end
718
719
@test outs == 1 : 5
719
720
end
720
721
721
- # Args
722
+ # Test macro parsing for interpolating into Args
722
723
@test fetch (Threads. @spawn 2 + $ 2) == 4
723
724
@test fetch (Threads. @spawn Int ($ (2.0 ))) == 2
724
725
a = 2
725
726
@test fetch (Threads. @spawn * ($ a,$ a)) == a^ 2
726
- # kwargs
727
+ # Test macro parsing for interpolating into kwargs
727
728
@test fetch (Threads. @spawn sort ($ ([3 2 ; 1 0 ]), dims= 2 )) == [2 3 ; 0 1 ]
728
729
@test fetch (Threads. @spawn sort ([3 $ 2; 1 $ 0]; dims= $ 2)) == [2 3 ; 0 1 ]
729
730
730
- # Supports multiple levels of interpolation
731
- @test fetch (Threads. @spawn " $($ a) " ) == " $a "
732
- let a = 1
733
- # Interpolate the current value of `a` vs the value of `a` in the closure
734
- t = Threads. @spawn :(+ ($$ a, $ a, a))
735
- a = 2 # update `a` after spawning
736
- @test fetch (t) == Expr (:call , :+ , 1 , 2 , :a )
737
- end
738
-
739
- # Test the difference between different levels of interpolation
740
- let
741
- oneinterp = Vector {Any} (undef, 5 )
742
- twointerps = Vector {Any} (undef, 5 )
743
- @sync begin
744
- local i = 1
745
- while i <= 5
746
- Threads. @spawn setindex! (oneinterp, :($ i), $ i)
747
- Threads. @spawn setindex! (twointerps, :($ ($ i)), $ i)
748
- i += 1
731
+ # Test macro parsing supports multiple levels of interpolation
732
+ @testset " spawn macro multiple levels of interpolation" begin
733
+ # Use `ch` to synchronize within the tests to run after the local variables are
734
+ # updated, showcasing the problem and the solution.
735
+ ch = Channel () # (This synchronization fixes test failure reported in #34141.)
736
+
737
+ @test fetch (Threads. @spawn " $($ a) " ) == " $a "
738
+ let a = 1
739
+ # Interpolate the current value of `a` vs the value of `a` in the closure
740
+ t = Threads. @spawn (take! (ch); :(+ ($$ a, $ a, a)))
741
+ a = 2 # update `a` after spawning, before `t` runs
742
+ put! (ch, nothing ) # now run t
743
+ @test fetch (t) == Expr (:call , :+ , 1 , 2 , :a )
744
+ end
745
+
746
+ # Test the difference between different levels of interpolation
747
+ # Without interpolation, each spawned task sees the last value of `i` (6);
748
+ # with interpolation, each spawned task has the value of `i` at time of `@spawn`.
749
+ let
750
+ oneinterp = Vector {Any} (undef, 5 )
751
+ twointerps = Vector {Any} (undef, 5 )
752
+ @sync begin
753
+ local i = 1
754
+ while i <= 5
755
+ Threads. @spawn (take! (ch); setindex! (oneinterp, :($ i), $ i))
756
+ Threads. @spawn (take! (ch); setindex! (twointerps, :($ ($ i)), $ i))
757
+ i += 1
758
+ end
759
+ for _ in 1 : 10 ; put! (ch, nothing ); end # Now run all the tasks.
749
760
end
761
+ # The first definition _didn't_ interpolate i
762
+ @test oneinterp == fill (6 , 5 )
763
+ # The second definition _did_ interpolate i
764
+ @test twointerps == 1 : 5
750
765
end
751
- # The first definition _didn't_ escape i
752
- @test oneinterp == fill (6 , 5 )
753
- # The second definition _did_ escape i
754
- @test twointerps == 1 : 5
755
766
end
756
767
end
757
768
770
781
@test fetch (@async :($ ($ a))) == a
771
782
@test fetch (@async " $($ a) " ) == " $a "
772
783
end
773
-
774
- # errors inside @threads
775
- function _atthreads_with_error (a, err)
776
- Threads. @threads for i in eachindex (a)
777
- if err
778
- error (" failed" )
779
- end
780
- a[i] = Threads. threadid ()
781
- end
782
- a
783
- end
784
- @test_throws TaskFailedException _atthreads_with_error (zeros (nthreads ()), true )
785
- let a = zeros (nthreads ())
786
- _atthreads_with_error (a, false )
787
- @test a == [1 : nthreads ();]
788
- end
0 commit comments