@@ -87,23 +87,67 @@ macro_rules! tracked_call {
8787 } ;
8888
8989 let mut w = $crate:: imp:: get_writer( ) ;
90- if let :: std:: option:: Option :: Some ( w) = & mut * w {
91- w. frame( TRACKED_ID ) . unwrap( ) ;
92- // TODO is there a way to drop w before calling f to shorten the critical section here?
93- $f( $(
94- {
95- let arg = $arg;
96- $crate:: imp:: ArgumentEncode :: write( & arg, & mut * * w) . expect( "write to succeed" ) ;
97- arg
98- }
99- ) ,*
100- )
90+ if w. is_some( ) {
91+ w. as_mut( ) . unwrap( ) . frame( TRACKED_ID ) . unwrap( ) ;
92+ let mut w_opt = Some ( w) ;
93+ $crate:: tracked_call! { is_last_arg( $f, w_opt) : ( ) $( $arg ) ,* }
10194 } else {
102- drop( w) ;
10395 $f( $( $arg ) ,* )
10496 }
10597 }
10698 } ;
99+ // munch non-last arg
100+ (
101+ is_last_arg( $f: ident, $w: ident) : (
102+ $( ( $out: expr, $last: literal) ) ,*
103+ )
104+ $arg: expr, $( $args: expr ) ,+
105+ ) => {
106+ $crate:: tracked_call! {
107+ is_last_arg( $f, $w) : (
108+ $( ( $out, $last ) , ) *
109+ ( $arg, false )
110+ )
111+ $( $args ) ,+
112+ }
113+ } ;
114+ // munch last arg
115+ (
116+ is_last_arg( $f: ident, $w: ident) : (
117+ $( ( $out: expr, $last: literal) ) ,*
118+ )
119+ $arg: expr $( , ) ?
120+ ) => {
121+ $crate:: tracked_call! {
122+ is_last_arg( $f, $w) : (
123+ $( ( $out, $last ) , ) *
124+ ( $arg, true )
125+ )
126+
127+ }
128+ } ;
129+ // call with some args
130+ ( is_last_arg( $f: ident, $w: ident) : ( $( ( $arg: expr, $last: literal) ) ,+ ) ) => {
131+ $f(
132+ $(
133+ {
134+ let arg = $arg;
135+ $crate:: imp:: ArgumentEncode :: write( & arg, & mut * * ( $w. as_deref_mut( ) . map( Option :: as_mut) . flatten( ) . expect( "lock to be held" ) ) ) . expect( "write to succeed" ) ;
136+ if $last {
137+ // release lock on recording
138+ :: std:: mem:: drop( :: std:: mem:: take( & mut $w) ) ;
139+ }
140+ arg
141+ }
142+ ) ,+
143+ )
144+ } ;
145+ // call with no args
146+ ( is_last_arg( $f: ident, $w: ident) : ( ) ) => {
147+ :: std:: mem:: drop( $w) ;
148+ $f( )
149+ } ;
150+
107151}
108152
109153pub struct Writer ( BufWriter < File > ) ;
0 commit comments