@@ -13,16 +13,32 @@ use std::{
13
13
atomic:: { AtomicBool , Ordering } ,
14
14
Arc , Mutex ,
15
15
} ,
16
+ thread,
17
+ time:: Duration ,
16
18
} ;
17
19
20
+ ///
21
+ #[ derive( PartialEq ) ]
22
+ pub enum FetchStatus {
23
+ /// previous fetch still running
24
+ Pending ,
25
+ /// no change expected
26
+ NoChange ,
27
+ /// new walk was started
28
+ Started ,
29
+ }
30
+
18
31
///
19
32
pub struct AsyncLog {
20
33
current : Arc < Mutex < Vec < Oid > > > ,
21
34
sender : Sender < AsyncNotification > ,
22
35
pending : Arc < AtomicBool > ,
36
+ background : Arc < AtomicBool > ,
23
37
}
24
38
25
- static LIMIT_COUNT : usize = 1000 ;
39
+ static LIMIT_COUNT : usize = 3000 ;
40
+ static SLEEP_FOREGROUND : Duration = Duration :: from_millis ( 2 ) ;
41
+ static SLEEP_BACKGROUND : Duration = Duration :: from_millis ( 1000 ) ;
26
42
27
43
impl AsyncLog {
28
44
///
@@ -31,6 +47,7 @@ impl AsyncLog {
31
47
current : Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ,
32
48
sender,
33
49
pending : Arc :: new ( AtomicBool :: new ( false ) ) ,
50
+ background : Arc :: new ( AtomicBool :: new ( false ) ) ,
34
51
}
35
52
}
36
53
@@ -58,6 +75,11 @@ impl AsyncLog {
58
75
self . pending . load ( Ordering :: Relaxed )
59
76
}
60
77
78
+ ///
79
+ pub fn set_background ( & mut self ) {
80
+ self . background . store ( true , Ordering :: Relaxed )
81
+ }
82
+
61
83
///
62
84
fn current_head ( & self ) -> Result < Oid > {
63
85
Ok ( self . current . lock ( ) ?. first ( ) . map_or ( Oid :: zero ( ) , |f| * f) )
@@ -79,29 +101,44 @@ impl AsyncLog {
79
101
}
80
102
81
103
///
82
- pub fn fetch ( & mut self ) -> Result < ( ) > {
83
- if !self . is_pending ( ) && self . head_changed ( ) ? {
84
- self . clear ( ) ?;
104
+ pub fn fetch ( & mut self ) -> Result < FetchStatus > {
105
+ self . background . store ( false , Ordering :: Relaxed ) ;
85
106
86
- let arc_current = Arc :: clone ( & self . current ) ;
87
- let sender = self . sender . clone ( ) ;
88
- let arc_pending = Arc :: clone ( & self . pending ) ;
89
-
90
- rayon_core:: spawn ( move || {
91
- scope_time ! ( "async::revlog" ) ;
107
+ if self . is_pending ( ) {
108
+ return Ok ( FetchStatus :: Pending ) ;
109
+ }
92
110
93
- arc_pending. store ( true , Ordering :: Relaxed ) ;
94
- AsyncLog :: fetch_helper ( arc_current, & sender)
95
- . expect ( "failed to fetch" ) ;
96
- arc_pending. store ( false , Ordering :: Relaxed ) ;
97
- Self :: notify ( & sender) ;
98
- } ) ;
111
+ if !self . head_changed ( ) ? {
112
+ return Ok ( FetchStatus :: NoChange ) ;
99
113
}
100
- Ok ( ( ) )
114
+
115
+ self . clear ( ) ?;
116
+
117
+ let arc_current = Arc :: clone ( & self . current ) ;
118
+ let sender = self . sender . clone ( ) ;
119
+ let arc_pending = Arc :: clone ( & self . pending ) ;
120
+ let arc_background = Arc :: clone ( & self . background ) ;
121
+
122
+ rayon_core:: spawn ( move || {
123
+ scope_time ! ( "async::revlog" ) ;
124
+
125
+ arc_pending. store ( true , Ordering :: Relaxed ) ;
126
+ AsyncLog :: fetch_helper (
127
+ arc_current,
128
+ arc_background,
129
+ & sender,
130
+ )
131
+ . expect ( "failed to fetch" ) ;
132
+ arc_pending. store ( false , Ordering :: Relaxed ) ;
133
+ Self :: notify ( & sender) ;
134
+ } ) ;
135
+
136
+ Ok ( FetchStatus :: Started )
101
137
}
102
138
103
139
fn fetch_helper (
104
140
arc_current : Arc < Mutex < Vec < Oid > > > ,
141
+ arc_background : Arc < AtomicBool > ,
105
142
sender : & Sender < AsyncNotification > ,
106
143
) -> Result < ( ) > {
107
144
let mut entries = Vec :: with_capacity ( LIMIT_COUNT ) ;
@@ -121,6 +158,14 @@ impl AsyncLog {
121
158
break ;
122
159
} else {
123
160
Self :: notify ( & sender) ;
161
+
162
+ let sleep_duration =
163
+ if arc_background. load ( Ordering :: Relaxed ) {
164
+ SLEEP_BACKGROUND
165
+ } else {
166
+ SLEEP_FOREGROUND
167
+ } ;
168
+ thread:: sleep ( sleep_duration) ;
124
169
}
125
170
}
126
171
0 commit comments