@@ -14,8 +14,8 @@ defmodule Module.ParallelChecker do
1414 @ doc """
1515 Initializes the parallel checker process.
1616 """
17- def start_link ( schedulers \\ nil ) do
18- :proc_lib . start_link ( __MODULE__ , :init , [ schedulers ] )
17+ def start_link ( opts \\ [ ] ) do
18+ :proc_lib . start_link ( __MODULE__ , :init , [ opts ] )
1919 end
2020
2121 @ doc """
@@ -114,15 +114,15 @@ defmodule Module.ParallelChecker do
114114 end
115115
116116 send ( pid , { __MODULE__ , module , warnings } )
117- send ( checker , { __MODULE__ , :done } )
117+ send ( checker , { __MODULE__ , :done , module } )
118118 end
119119
120120 { :DOWN , ^ mon_ref , _ , _ , _ } ->
121121 :ok
122122 end
123123 end )
124124
125- register ( checker , spawned , ref )
125+ register ( checker , module , spawned , ref )
126126 :ok
127127 end
128128
@@ -515,13 +515,13 @@ defmodule Module.ParallelChecker do
515515 :gen_server . call ( server , { :unlock , module , mode } , :infinity )
516516 end
517517
518- defp register ( server , pid , ref ) do
519- :gen_server . cast ( server , { :register , pid , ref } )
518+ defp register ( server , module , pid , ref ) do
519+ :gen_server . cast ( server , { :register , module , pid , ref } )
520520 end
521521
522522 ## Server callbacks
523523
524- def init ( schedulers ) do
524+ def init ( options ) do
525525 table = :ets . new ( __MODULE__ , [ :set , :public , { :read_concurrency , true } ] )
526526 :proc_lib . init_ack ( { :ok , { self ( ) , table } } )
527527
@@ -544,11 +544,26 @@ defmodule Module.ParallelChecker do
544544 end
545545 end
546546
547+ schedulers =
548+ Keyword . get_lazy ( options , :max_concurrency , fn ->
549+ max ( :erlang . system_info ( :schedulers_online ) , 2 )
550+ end )
551+
552+ threshold = Keyword . get ( options , :long_verification_threshold , 10 ) * 1000
553+
554+ callback =
555+ case Keyword . get ( options , :each_long_verification , fn _module , _pid -> :ok end ) do
556+ fun when is_function ( fun , 1 ) -> fn module , _pid -> fun . ( module ) end
557+ fun when is_function ( fun , 2 ) -> fun
558+ end
559+
547560 state = % {
548561 waiting: % { } ,
549562 modules: [ ] ,
550- spawned: 0 ,
551- schedulers: schedulers || max ( :erlang . system_info ( :schedulers_online ) , 2 ) ,
563+ spawned: % { } ,
564+ schedulers: schedulers ,
565+ threshold: threshold ,
566+ callback: callback ,
552567 protocols: [ ] ,
553568 table: table
554569 }
@@ -559,11 +574,11 @@ defmodule Module.ParallelChecker do
559574 def handle_call ( :start , _from , % { modules: modules , protocols: protocols , table: table } = state ) do
560575 :ets . insert ( table , Enum . map ( protocols , & { & 1 , :uncached } ) )
561576
562- for { pid , ref } <- modules do
577+ for { _module , pid , ref } <- modules do
563578 send ( pid , { ref , :cache } )
564579 end
565580
566- for { _pid , ref } <- modules do
581+ for { _module , _pid , ref } <- modules do
567582 receive do
568583 { ^ ref , :cached } -> :ok
569584 end
@@ -594,30 +609,38 @@ defmodule Module.ParallelChecker do
594609 { :reply , :ok , % { state | waiting: waiting , protocols: protocols } }
595610 end
596611
597- def handle_info ( { __MODULE__ , :done } , state ) do
598- state = % { state | spawned: state . spawned - 1 }
599- { :noreply , run_checkers ( state ) }
612+ def handle_info ( { __MODULE__ , :timeout , module , pid } , state ) do
613+ state . callback . ( module , pid )
614+ { :noreply , state }
615+ end
616+
617+ def handle_info ( { __MODULE__ , :done , module } , state ) do
618+ { timer , spawned } = Map . pop! ( state . spawned , module )
619+ Process . cancel_timer ( timer )
620+ { :noreply , run_checkers ( % { state | spawned: spawned } ) }
600621 end
601622
602623 def handle_info ( { __MODULE__ , :stop } , state ) do
603624 { :stop , :normal , state }
604625 end
605626
606- def handle_cast ( { :register , pid , ref } , % { modules: modules } = state ) do
607- { :noreply , % { state | modules: [ { pid , ref } | modules ] } }
627+ def handle_cast ( { :register , module , pid , ref } , % { modules: modules } = state ) do
628+ { :noreply , % { state | modules: [ { module , pid , ref } | modules ] } }
608629 end
609630
610631 defp run_checkers ( % { modules: [ ] } = state ) do
611632 state
612633 end
613634
614635 defp run_checkers ( % { spawned: spawned , schedulers: schedulers } = state )
615- when spawned >= schedulers do
636+ when map_size ( spawned ) >= schedulers do
616637 state
617638 end
618639
619- defp run_checkers ( % { modules: [ { pid , ref } | modules ] } = state ) do
640+ defp run_checkers ( % { modules: [ { module , pid , ref } | modules ] } = state ) do
620641 send ( pid , { ref , :check } )
621- run_checkers ( % { state | modules: modules , spawned: state . spawned + 1 } )
642+ timer = Process . send_after ( self ( ) , { __MODULE__ , :timeout , module , pid } , state . threshold )
643+ spawned = Map . put ( state . spawned , module , timer )
644+ run_checkers ( % { state | modules: modules , spawned: spawned } )
622645 end
623646end
0 commit comments