@@ -342,7 +342,7 @@ defmodule Kernel.ParallelCompiler do
342
342
Code . prepend_path ( path )
343
343
344
344
Enum . flat_map ( result , fn
345
- { { :module , module } , binary } when is_binary ( binary ) ->
345
+ { { :module , module } , { binary , _ } } when is_binary ( binary ) ->
346
346
full_path = Path . join ( path , Atom . to_string ( module ) <> ".beam" )
347
347
File . write! ( full_path , binary )
348
348
if timestamp , do: File . touch! ( full_path , timestamp )
@@ -354,7 +354,7 @@ defmodule Kernel.ParallelCompiler do
354
354
end
355
355
356
356
defp write_module_binaries ( result , _output , _timestamp ) do
357
- for { { :module , module } , binary } when is_binary ( binary ) <- result , do: module
357
+ for { { :module , module } , { binary , _ } } when is_binary ( binary ) <- result , do: module
358
358
end
359
359
360
360
## Verification
@@ -369,7 +369,7 @@ defmodule Kernel.ParallelCompiler do
369
369
370
370
defp maybe_check_modules ( result , runtime_modules , state ) do
371
371
compiled_modules =
372
- for { { :module , module } , binary } when is_binary ( binary ) <- result ,
372
+ for { { :module , module } , { binary , _ } } when is_binary ( binary ) <- result ,
373
373
do: module
374
374
375
375
profile (
@@ -585,7 +585,7 @@ defmodule Kernel.ParallelCompiler do
585
585
end
586
586
587
587
defp count_modules ( result ) do
588
- Enum . count ( result , & match? ( { { :module , _ } , binary } when is_binary ( binary ) , & 1 ) )
588
+ Enum . count ( result , & match? ( { { :module , _ } , { binary , _ } } when is_binary ( binary ) , & 1 ) )
589
589
end
590
590
591
591
defp each_cycle_return ( { kind , modules , warnings } ) , do: { kind , modules , warnings }
@@ -664,19 +664,28 @@ defmodule Kernel.ParallelCompiler do
664
664
send ( child , { ref , load? } )
665
665
spawn_workers ( queue , spawned , waiting , files , result , warnings , errors , state )
666
666
667
+ { { :module_loaded , module } , _ref , _type , _pid , _reason } ->
668
+ result =
669
+ Map . update! ( result , { :module , module } , fn { binary , _loader } -> { binary , true } end )
670
+
671
+ spawn_workers ( queue , spawned , waiting , files , result , warnings , errors , state )
672
+
667
673
{ :module_available , child , ref , file , module , binary , loaded? } ->
668
674
state . each_module . ( file , module , binary )
669
675
670
- available =
676
+ { available , load_status } =
671
677
case Map . get ( result , { :module , module } ) do
678
+ # We prefer to load in the client, if possible,
679
+ # to avoid locking the compilation server.
680
+ [ _ | _ ] = pids when loaded? ->
681
+ { Enum . map ( pids , & { & 1 , :found } ) , loaded? }
682
+
672
683
[ _ | _ ] = pids ->
673
- # We prefer to load in the client, if possible,
674
- # to avoid locking the compilation server.
675
- loaded? or load_module ( module , binary , state )
676
- Enum . map ( pids , & { & 1 , :found } )
684
+ pid = load_module ( module , binary , state . dest )
685
+ { Enum . map ( pids , & { & 1 , { :loading , pid } } ) , pid }
677
686
678
687
_ ->
679
- [ ]
688
+ { [ ] , loaded? }
680
689
end
681
690
682
691
# Release the module loader which is waiting for an ack
@@ -687,7 +696,7 @@ defmodule Kernel.ParallelCompiler do
687
696
spawned ,
688
697
waiting ,
689
698
files ,
690
- Map . put ( result , { :module , module } , binary ) ,
699
+ Map . put ( result , { :module , module } , { binary , load_status } ) ,
691
700
warnings ,
692
701
errors ,
693
702
state
@@ -707,8 +716,8 @@ defmodule Kernel.ParallelCompiler do
707
716
{ waiting , files , result } =
708
717
if not is_list ( available_or_pending ) or on in defining do
709
718
# If what we are waiting on was defined but not loaded, we do it now.
710
- load_pending ( kind , on , result , state )
711
- send ( child_pid , { ref , :found } )
719
+ { reply , result } = load_pending ( kind , on , result , state )
720
+ send ( child_pid , { ref , reply } )
712
721
{ waiting , files , result }
713
722
else
714
723
waiting = Map . put ( waiting , child_pid , { kind , ref , file_pid , on , defining , deadlock } )
@@ -803,27 +812,49 @@ defmodule Kernel.ParallelCompiler do
803
812
end
804
813
805
814
defp load_pending ( kind , module , result , state ) do
806
- with true <- kind in [ :module , :struct ] ,
807
- % { { :module , ^ module } => binary } when is_binary ( binary ) <- result ,
808
- false <- :erlang . module_loaded ( module ) do
809
- load_module ( module , binary , state )
815
+ case result do
816
+ % { { :module , ^ module } => { binary , load_status } }
817
+ when kind in [ :module , :struct ] and is_binary ( binary ) ->
818
+ case load_status do
819
+ true ->
820
+ { :found , result }
821
+
822
+ false ->
823
+ pid = load_module ( module , binary , state . dest )
824
+ result = Map . put ( result , { :module , module } , { binary , pid } )
825
+ { { :loading , pid } , result }
826
+
827
+ pid when is_pid ( pid ) ->
828
+ { { :loading , pid } , result }
829
+ end
830
+
831
+ _ ->
832
+ { :found , result }
810
833
end
811
834
end
812
835
813
- defp load_module ( module , binary , state ) do
814
- beam_location =
815
- case state . dest do
816
- nil ->
817
- [ ]
818
-
819
- dest ->
820
- :filename . join (
821
- :elixir_utils . characters_to_list ( dest ) ,
822
- Atom . to_charlist ( module ) ++ ~c" .beam"
823
- )
824
- end
836
+ defp load_module ( module , binary , dest ) do
837
+ { pid , _ref } =
838
+ :erlang . spawn_opt (
839
+ fn ->
840
+ beam_location =
841
+ case dest do
842
+ nil ->
843
+ [ ]
844
+
845
+ dest ->
846
+ :filename . join (
847
+ :elixir_utils . characters_to_list ( dest ) ,
848
+ Atom . to_charlist ( module ) ++ ~c" .beam"
849
+ )
850
+ end
851
+
852
+ :code . load_binary ( module , beam_location , binary )
853
+ end ,
854
+ monitor: [ tag: { :module_loaded , module } ]
855
+ )
825
856
826
- :code . load_binary ( module , beam_location , binary )
857
+ pid
827
858
end
828
859
829
860
defp update_result ( result , kind , module , value ) do
0 commit comments