@@ -324,7 +324,7 @@ defmodule Kernel.ParallelCompiler do
324
324
Code . prepend_path ( path )
325
325
326
326
Enum . flat_map ( result , fn
327
- { { :module , module } , binary } when is_binary ( binary ) ->
327
+ { { :module , module } , { binary , _ } } when is_binary ( binary ) ->
328
328
full_path = Path . join ( path , Atom . to_string ( module ) <> ".beam" )
329
329
File . write! ( full_path , binary )
330
330
if timestamp , do: File . touch! ( full_path , timestamp )
@@ -336,7 +336,7 @@ defmodule Kernel.ParallelCompiler do
336
336
end
337
337
338
338
defp write_module_binaries ( result , _output , _timestamp ) do
339
- for { { :module , module } , binary } when is_binary ( binary ) <- result , do: module
339
+ for { { :module , module } , { binary , _ } } when is_binary ( binary ) <- result , do: module
340
340
end
341
341
342
342
## Verification
@@ -350,7 +350,7 @@ defmodule Kernel.ParallelCompiler do
350
350
351
351
defp maybe_check_modules ( result , runtime_modules , state ) do
352
352
compiled_modules =
353
- for { { :module , module } , binary } when is_binary ( binary ) <- result ,
353
+ for { { :module , module } , { binary , _ } } when is_binary ( binary ) <- result ,
354
354
do: module
355
355
356
356
profile (
@@ -566,7 +566,7 @@ defmodule Kernel.ParallelCompiler do
566
566
end
567
567
568
568
defp count_modules ( result ) do
569
- Enum . count ( result , & match? ( { { :module , _ } , binary } when is_binary ( binary ) , & 1 ) )
569
+ Enum . count ( result , & match? ( { { :module , _ } , { binary , _ } } when is_binary ( binary ) , & 1 ) )
570
570
end
571
571
572
572
defp each_cycle_return ( { kind , modules , warnings } ) , do: { kind , modules , warnings }
@@ -645,19 +645,28 @@ defmodule Kernel.ParallelCompiler do
645
645
send ( child , { ref , load? } )
646
646
spawn_workers ( queue , spawned , waiting , files , result , warnings , errors , state )
647
647
648
+ { { :module_loaded , module } , _ref , _type , _pid , _reason } ->
649
+ result =
650
+ Map . update! ( result , { :module , module } , fn { binary , _loader } -> { binary , true } end )
651
+
652
+ spawn_workers ( queue , spawned , waiting , files , result , warnings , errors , state )
653
+
648
654
{ :module_available , child , ref , file , module , binary , loaded? } ->
649
655
state . each_module . ( file , module , binary )
650
656
651
- available =
657
+ { available , load_status } =
652
658
case Map . get ( result , { :module , module } ) do
659
+ # We prefer to load in the client, if possible,
660
+ # to avoid locking the compilation server.
661
+ [ _ | _ ] = pids when loaded? ->
662
+ { Enum . map ( pids , & { & 1 , :found } ) , loaded? }
663
+
653
664
[ _ | _ ] = pids ->
654
- # We prefer to load in the client, if possible,
655
- # to avoid locking the compilation server.
656
- loaded? or load_module ( module , binary , state )
657
- Enum . map ( pids , & { & 1 , :found } )
665
+ pid = load_module ( module , binary , state . dest )
666
+ { Enum . map ( pids , & { & 1 , { :loading , pid } } ) , pid }
658
667
659
668
_ ->
660
- [ ]
669
+ { [ ] , loaded? }
661
670
end
662
671
663
672
# Release the module loader which is waiting for an ack
@@ -668,7 +677,7 @@ defmodule Kernel.ParallelCompiler do
668
677
spawned ,
669
678
waiting ,
670
679
files ,
671
- Map . put ( result , { :module , module } , binary ) ,
680
+ Map . put ( result , { :module , module } , { binary , load_status } ) ,
672
681
warnings ,
673
682
errors ,
674
683
state
@@ -688,8 +697,8 @@ defmodule Kernel.ParallelCompiler do
688
697
{ waiting , files , result } =
689
698
if not is_list ( available_or_pending ) or on in defining do
690
699
# If what we are waiting on was defined but not loaded, we do it now.
691
- load_pending ( kind , on , result , state )
692
- send ( child_pid , { ref , :found } )
700
+ { reply , result } = load_pending ( kind , on , result , state )
701
+ send ( child_pid , { ref , reply } )
693
702
{ waiting , files , result }
694
703
else
695
704
waiting = Map . put ( waiting , child_pid , { kind , ref , file_pid , on , defining , deadlock } )
@@ -784,27 +793,49 @@ defmodule Kernel.ParallelCompiler do
784
793
end
785
794
786
795
defp load_pending ( kind , module , result , state ) do
787
- with true <- kind in [ :module , :struct ] ,
788
- % { { :module , ^ module } => binary } when is_binary ( binary ) <- result ,
789
- false <- :erlang . module_loaded ( module ) do
790
- load_module ( module , binary , state )
796
+ case result do
797
+ % { { :module , ^ module } => { binary , load_status } }
798
+ when kind in [ :module , :struct ] and is_binary ( binary ) ->
799
+ case load_status do
800
+ true ->
801
+ { :found , result }
802
+
803
+ false ->
804
+ pid = load_module ( module , binary , state . dest )
805
+ result = Map . put ( result , { :module , module } , { binary , pid } )
806
+ { { :loading , pid } , result }
807
+
808
+ pid when is_pid ( pid ) ->
809
+ { { :loading , pid } , result }
810
+ end
811
+
812
+ _ ->
813
+ { :found , result }
791
814
end
792
815
end
793
816
794
- defp load_module ( module , binary , state ) do
795
- beam_location =
796
- case state . dest do
797
- nil ->
798
- [ ]
799
-
800
- dest ->
801
- :filename . join (
802
- :elixir_utils . characters_to_list ( dest ) ,
803
- Atom . to_charlist ( module ) ++ ~c" .beam"
804
- )
805
- end
817
+ defp load_module ( module , binary , dest ) do
818
+ { pid , _ref } =
819
+ :erlang . spawn_opt (
820
+ fn ->
821
+ beam_location =
822
+ case dest do
823
+ nil ->
824
+ [ ]
825
+
826
+ dest ->
827
+ :filename . join (
828
+ :elixir_utils . characters_to_list ( dest ) ,
829
+ Atom . to_charlist ( module ) ++ ~c" .beam"
830
+ )
831
+ end
832
+
833
+ :code . load_binary ( module , beam_location , binary )
834
+ end ,
835
+ monitor: [ tag: { :module_loaded , module } ]
836
+ )
806
837
807
- :code . load_binary ( module , beam_location , binary )
838
+ pid
808
839
end
809
840
810
841
defp update_result ( result , kind , module , value ) do
0 commit comments