@@ -502,6 +502,10 @@ impl ClientStats {
502502/// The monitor trait keeps track of all the client's monitor, and offers methods to display them.
503503pub trait Monitor {
504504 /// The client monitor (mutable)
505+ ///
506+ /// This method is for internal usage only, you shall never call this method directly.
507+ /// If you want to update one client stats, use [`update_client_stats_for`][Self::update_client_stats_for]. If you
508+ /// want to update all client stats together, use [`update_all_client_stats`][Self::update_all_client_stats].
505509 fn client_stats_mut ( & mut self ) -> & mut Vec < ClientStats > ;
506510
507511 /// The client monitor
@@ -571,19 +575,33 @@ pub trait Monitor {
571575 ..ClientStats :: default ( )
572576 } ) ;
573577 }
574- let new_stat = self . client_stats_mut_for ( client_id) ;
575- if !new_stat. enabled {
576- let timestamp = current_time ( ) ;
577- // I have never seen this man in my life
578- new_stat. start_time = timestamp;
579- new_stat. last_window_time = timestamp;
580- new_stat. enabled = true ;
581- }
578+ self . update_client_stats_for ( client_id, |new_stat| {
579+ if !new_stat. enabled {
580+ let timestamp = current_time ( ) ;
581+ // I have never seen this man in my life
582+ new_stat. start_time = timestamp;
583+ new_stat. last_window_time = timestamp;
584+ new_stat. enabled = true ;
585+ }
586+ } ) ;
587+ }
588+
589+ /// Update sepecific client stats.
590+ ///
591+ /// The update function is restricted as `Fn` instead of `FnMut` or `FnOnce` since in some
592+ /// monitors, the `update` will be called multiple times, and is assumed as stateless.
593+ fn update_client_stats_for < T , F : Fn ( & mut ClientStats ) -> T > (
594+ & mut self ,
595+ client_id : ClientId ,
596+ update : F ,
597+ ) -> T {
598+ let client_stat = & mut self . client_stats_mut ( ) [ client_id. 0 as usize ] ;
599+ update ( client_stat)
582600 }
583601
584- /// Get mutable reference to client stats
585- fn client_stats_mut_for ( & mut self , client_id : ClientId ) -> & mut ClientStats {
586- & mut self . client_stats_mut ( ) [ client_id . 0 as usize ]
602+ /// Update all client stats. This will clear all previous client stats, and fill in the new client stats.
603+ fn update_all_client_stats ( & mut self , new_client_stats : Vec < ClientStats > ) {
604+ * self . client_stats_mut ( ) = new_client_stats ;
587605 }
588606
589607 /// Get immutable reference to client stats
@@ -791,7 +809,7 @@ where
791809
792810 if self . print_user_monitor {
793811 self . client_stats_insert ( sender_id) ;
794- let client = self . client_stats_mut_for ( sender_id) ;
812+ let client = self . client_stats_for ( sender_id) ;
795813 for ( key, val) in & client. user_monitor {
796814 write ! ( fmt, ", {key}: {val}" ) . unwrap ( ) ;
797815 }
@@ -1303,18 +1321,17 @@ impl Default for ClientPerfMonitor {
13031321 }
13041322}
13051323
1306- /// A combined monitor consisting of multiple [`Monitor`]s
1324+ // The client stats of first and second monitor will always be maintained
1325+ // to be consistent
1326+ /// A combined monitor consisting of multiple [`Monitor`]s.
1327+ ///
1328+ /// Note that the `CombinedMonitor` should never be the base monitor of other wrapper
1329+ /// monitors.
13071330#[ derive( Debug , Clone ) ]
13081331pub struct CombinedMonitor < A , B > {
13091332 first : A ,
13101333 second : B ,
13111334 start_time : Duration ,
1312- /// Client stats. This will be maintained to be consistent with
1313- /// client stats of first and second monitor.
1314- ///
1315- /// Currently, the client stats will be synced to first and second
1316- /// before each display call.
1317- client_stats : Vec < ClientStats > ,
13181335}
13191336
13201337impl < A : Monitor , B : Monitor > CombinedMonitor < A , B > {
@@ -1323,22 +1340,24 @@ impl<A: Monitor, B: Monitor> CombinedMonitor<A, B> {
13231340 let start_time = current_time ( ) ;
13241341 first. set_start_time ( start_time) ;
13251342 second. set_start_time ( start_time) ;
1343+ first. update_all_client_stats ( vec ! [ ] ) ;
1344+ second. update_all_client_stats ( vec ! [ ] ) ;
13261345 Self {
13271346 first,
13281347 second,
13291348 start_time,
1330- client_stats : vec ! [ ] ,
13311349 }
13321350 }
13331351}
13341352
13351353impl < A : Monitor , B : Monitor > Monitor for CombinedMonitor < A , B > {
1354+ /// Never call this method.
13361355 fn client_stats_mut ( & mut self ) -> & mut Vec < ClientStats > {
1337- & mut self . client_stats
1356+ panic ! ( "client_stats_mut of CombinedMonitor should never be called" )
13381357 }
13391358
13401359 fn client_stats ( & self ) -> & [ ClientStats ] {
1341- & self . client_stats
1360+ self . first . client_stats ( )
13421361 }
13431362
13441363 fn start_time ( & self ) -> Duration {
@@ -1351,15 +1370,42 @@ impl<A: Monitor, B: Monitor> Monitor for CombinedMonitor<A, B> {
13511370 self . second . set_start_time ( time) ;
13521371 }
13531372
1373+ fn client_stats_insert ( & mut self , client_id : ClientId ) {
1374+ self . first . client_stats_insert ( client_id) ;
1375+ self . second . client_stats_insert ( client_id) ;
1376+ }
1377+
1378+ #[ inline]
1379+ fn execs_per_sec ( & mut self ) -> f64 {
1380+ let execs_per_sec = self . first . execs_per_sec ( ) ;
1381+ let _ = self . second . execs_per_sec ( ) ;
1382+ execs_per_sec
1383+ }
1384+
13541385 fn display ( & mut self , event_msg : & str , sender_id : ClientId ) {
1355- self . first . client_stats_mut ( ) . clone_from ( & self . client_stats ) ;
13561386 self . first . display ( event_msg, sender_id) ;
1357- self . second
1358- . client_stats_mut ( )
1359- . clone_from ( & self . client_stats ) ;
13601387 self . second . display ( event_msg, sender_id) ;
13611388 }
13621389
1390+ /// The `update` will be called multiple times, and the result of first
1391+ /// invocation will be returned. Since the client stats are guaranteed
1392+ /// to be consistent across first and second monitor, the result should be
1393+ /// the same.
1394+ fn update_client_stats_for < T , F : Fn ( & mut ClientStats ) -> T > (
1395+ & mut self ,
1396+ client_id : ClientId ,
1397+ update : F ,
1398+ ) -> T {
1399+ let res = self . first . update_client_stats_for ( client_id, & update) ;
1400+ let _ = self . second . update_client_stats_for ( client_id, & update) ;
1401+ res
1402+ }
1403+
1404+ fn update_all_client_stats ( & mut self , new_client_stats : Vec < ClientStats > ) {
1405+ self . first . update_all_client_stats ( new_client_stats. clone ( ) ) ;
1406+ self . second . update_all_client_stats ( new_client_stats) ;
1407+ }
1408+
13631409 fn aggregate ( & mut self , name : & str ) {
13641410 self . first . aggregate ( name) ;
13651411 self . second . aggregate ( name) ;
0 commit comments