@@ -2820,10 +2820,12 @@ enum NotifyOption {
2820
2820
/// We allow callers to either always notify by constructing with `notify_on_drop` or choose to
2821
2821
/// notify or not based on whether relevant changes have been made, providing a closure to
2822
2822
/// `optionally_notify` which returns a `NotifyOption`.
2823
- struct PersistenceNotifierGuard<'a, F: FnMut () -> NotifyOption> {
2823
+ struct PersistenceNotifierGuard<'a, F: FnOnce () -> NotifyOption> {
2824
2824
event_persist_notifier: &'a Notifier,
2825
2825
needs_persist_flag: &'a AtomicBool,
2826
- should_persist: F,
2826
+ // Always `Some` once initialized, but tracked as an `Option` to obtain the closure by value in
2827
+ // [`PersistenceNotifierGuard::drop`].
2828
+ should_persist: Option<F>,
2827
2829
// We hold onto this result so the lock doesn't get released immediately.
2828
2830
_read_guard: RwLockReadGuard<'a, ()>,
2829
2831
}
@@ -2838,20 +2840,20 @@ impl<'a> PersistenceNotifierGuard<'a, fn() -> NotifyOption> {
2838
2840
/// isn't ideal.
2839
2841
fn notify_on_drop<C: AChannelManager>(
2840
2842
cm: &'a C,
2841
- ) -> PersistenceNotifierGuard<'a, impl FnMut () -> NotifyOption> {
2843
+ ) -> PersistenceNotifierGuard<'a, impl FnOnce () -> NotifyOption> {
2842
2844
Self::optionally_notify(cm, || -> NotifyOption { NotifyOption::DoPersist })
2843
2845
}
2844
2846
2845
2847
#[rustfmt::skip]
2846
- fn optionally_notify<F: FnMut () -> NotifyOption, C: AChannelManager>(cm: &'a C, mut persist_check: F)
2847
- -> PersistenceNotifierGuard<'a, impl FnMut () -> NotifyOption> {
2848
+ fn optionally_notify<F: FnOnce () -> NotifyOption, C: AChannelManager>(cm: &'a C, persist_check: F)
2849
+ -> PersistenceNotifierGuard<'a, impl FnOnce () -> NotifyOption> {
2848
2850
let read_guard = cm.get_cm().total_consistency_lock.read().unwrap();
2849
2851
let force_notify = cm.get_cm().process_background_events();
2850
2852
2851
2853
PersistenceNotifierGuard {
2852
2854
event_persist_notifier: &cm.get_cm().event_persist_notifier,
2853
2855
needs_persist_flag: &cm.get_cm().needs_persist_flag,
2854
- should_persist: move || {
2856
+ should_persist: Some( move || {
2855
2857
// Pick the "most" action between `persist_check` and the background events
2856
2858
// processing and return that.
2857
2859
let notify = persist_check();
@@ -2862,7 +2864,7 @@ impl<'a> PersistenceNotifierGuard<'a, fn() -> NotifyOption> {
2862
2864
(_, NotifyOption::SkipPersistHandleEvents) => NotifyOption::SkipPersistHandleEvents,
2863
2865
_ => NotifyOption::SkipPersistNoEvents,
2864
2866
}
2865
- },
2867
+ }) ,
2866
2868
_read_guard: read_guard,
2867
2869
}
2868
2870
}
@@ -2878,15 +2880,22 @@ impl<'a> PersistenceNotifierGuard<'a, fn() -> NotifyOption> {
2878
2880
PersistenceNotifierGuard {
2879
2881
event_persist_notifier: &cm.get_cm().event_persist_notifier,
2880
2882
needs_persist_flag: &cm.get_cm().needs_persist_flag,
2881
- should_persist: persist_check,
2883
+ should_persist: Some( persist_check) ,
2882
2884
_read_guard: read_guard,
2883
2885
}
2884
2886
}
2885
2887
}
2886
2888
2887
- impl<'a, F: FnMut () -> NotifyOption> Drop for PersistenceNotifierGuard<'a, F> {
2889
+ impl<'a, F: FnOnce () -> NotifyOption> Drop for PersistenceNotifierGuard<'a, F> {
2888
2890
fn drop(&mut self) {
2889
- match (self.should_persist)() {
2891
+ let should_persist = match self.should_persist.take() {
2892
+ Some(should_persist) => should_persist,
2893
+ None => {
2894
+ debug_assert!(false);
2895
+ return;
2896
+ },
2897
+ };
2898
+ match should_persist() {
2890
2899
NotifyOption::DoPersist => {
2891
2900
self.needs_persist_flag.store(true, Ordering::Release);
2892
2901
self.event_persist_notifier.notify()
0 commit comments