@@ -254,6 +254,8 @@ impl Client {
254
254
/// On Unix and Windows this will clobber the `CARGO_MAKEFLAGS` environment
255
255
/// variables for the child process, and on Unix this will also allow the
256
256
/// two file descriptors for this client to be inherited to the child.
257
+ ///
258
+ /// On platforms other than Unix and Windows this panics.
257
259
pub fn configure ( & self , cmd : & mut Command ) {
258
260
let arg = self . inner . string_arg ( ) ;
259
261
// Older implementations of make use `--jobserver-fds` and newer
@@ -961,3 +963,94 @@ mod imp {
961
963
}
962
964
}
963
965
}
966
+
967
+ #[ cfg( not( any( unix, windows) ) ) ]
968
+ mod imp {
969
+ use std:: io;
970
+ use std:: sync:: Mutex ;
971
+ use std:: sync:: mpsc:: { self , SyncSender , Receiver } ;
972
+ use std:: thread:: { Builder , JoinHandle } ;
973
+ use std:: process:: Command ;
974
+
975
+ #[ derive( Debug ) ]
976
+ pub struct Client {
977
+ tx : SyncSender < ( ) > ,
978
+ rx : Mutex < Receiver < ( ) > > ,
979
+ }
980
+
981
+ #[ derive( Debug ) ]
982
+ pub struct Acquired ( ( ) ) ;
983
+
984
+ impl Client {
985
+ pub fn new ( limit : usize ) -> io:: Result < Client > {
986
+ let ( tx, rx) = mpsc:: sync_channel ( limit) ;
987
+ for _ in 0 ..limit {
988
+ tx. send ( ( ) ) . unwrap ( ) ;
989
+ }
990
+ Ok ( Client {
991
+ tx,
992
+ rx : Mutex :: new ( rx) ,
993
+ } )
994
+ }
995
+
996
+ pub unsafe fn open ( _s : & str ) -> Option < Client > {
997
+ None
998
+ }
999
+
1000
+ pub fn acquire ( & self ) -> io:: Result < Acquired > {
1001
+ self . rx . lock ( ) . unwrap ( ) . recv ( ) . unwrap ( ) ;
1002
+ Ok ( Acquired ( ( ) ) )
1003
+ }
1004
+
1005
+ pub fn release ( & self , _data : Option < & Acquired > ) -> io:: Result < ( ) > {
1006
+ self . tx . send ( ( ) ) . unwrap ( ) ;
1007
+ Ok ( ( ) )
1008
+ }
1009
+
1010
+ pub fn string_arg ( & self ) -> String {
1011
+ panic ! (
1012
+ "On this platform there is no cross process jobserver support,
1013
+ so Client::configure is not supported."
1014
+ ) ;
1015
+ }
1016
+
1017
+ pub fn configure ( & self , _cmd : & mut Command ) {
1018
+ unreachable ! ( ) ;
1019
+ }
1020
+ }
1021
+
1022
+ #[ derive( Debug ) ]
1023
+ pub struct Helper {
1024
+ thread : JoinHandle < ( ) > ,
1025
+ }
1026
+
1027
+ pub fn spawn_helper ( client : :: Client ,
1028
+ rx : Receiver < ( ) > ,
1029
+ mut f : Box < FnMut ( io:: Result < :: Acquired > ) + Send > )
1030
+ -> io:: Result < Helper >
1031
+ {
1032
+ let thread = Builder :: new ( ) . spawn ( move || {
1033
+ for ( ) in rx {
1034
+ let res = client. acquire ( ) ;
1035
+ f ( res) ;
1036
+ }
1037
+ } ) ?;
1038
+
1039
+ Ok ( Helper {
1040
+ thread : thread,
1041
+ } )
1042
+ }
1043
+
1044
+ impl Helper {
1045
+ pub fn join ( self ) {
1046
+ drop ( self . thread . join ( ) ) ;
1047
+ }
1048
+ }
1049
+ }
1050
+
1051
+ #[ test]
1052
+ fn no_helper_deadlock ( ) {
1053
+ let x = crate :: Client :: new ( 32 ) . unwrap ( ) ;
1054
+ let _y = x. clone ( ) ;
1055
+ std:: mem:: drop ( x. into_helper_thread ( |_| { } ) . unwrap ( ) ) ;
1056
+ }
0 commit comments