only ever call callbacks once

This commit is contained in:
pedrocarlo
2025-09-21 13:50:36 -03:00
parent 6b273af7e9
commit ffeb26b24a

View File

@@ -3,6 +3,7 @@ use crate::storage::sqlite3_ondisk::WAL_FRAME_HEADER_SIZE;
use crate::{BufferPool, CompletionError, Result};
use bitflags::bitflags;
use cfg_block::cfg_block;
use parking_lot::Once;
use std::cell::RefCell;
use std::fmt;
use std::ptr::NonNull;
@@ -142,6 +143,8 @@ struct CompletionInner {
// Thread safe with OnceLock
result: std::sync::OnceLock<Option<CompletionError>>,
needs_link: bool,
/// before calling callback we check if done is true
done: Once,
}
impl Debug for CompletionType {
@@ -169,6 +172,7 @@ impl Completion {
completion_type,
result: OnceLock::new(),
needs_link: false,
done: Once::new(),
}),
}
}
@@ -179,6 +183,7 @@ impl Completion {
completion_type,
result: OnceLock::new(),
needs_link: true,
done: Once::new(),
}),
}
}
@@ -258,36 +263,33 @@ impl Completion {
pub fn complete(&self, result: i32) {
let result = Ok(result);
match &self.inner.completion_type {
CompletionType::Read(r) => r.callback(result),
CompletionType::Write(w) => w.callback(result),
CompletionType::Sync(s) => s.callback(result), // fix
CompletionType::Truncate(t) => t.callback(result),
};
self.inner
.result
.set(None)
.expect("result must be set only once");
self.callback(result);
}
pub fn error(&self, err: CompletionError) {
let result = Err(err);
match &self.inner.completion_type {
CompletionType::Read(r) => r.callback(result),
CompletionType::Write(w) => w.callback(result),
CompletionType::Sync(s) => s.callback(result), // fix
CompletionType::Truncate(t) => t.callback(result),
};
self.inner
.result
.set(Some(err))
.expect("result must be set only once");
self.callback(result);
}
pub fn abort(&self) {
self.error(CompletionError::Aborted);
}
fn callback(&self, result: Result<i32, CompletionError>) {
self.inner.done.call_once(|| {
match &self.inner.completion_type {
CompletionType::Read(r) => r.callback(result),
CompletionType::Write(w) => w.callback(result),
CompletionType::Sync(s) => s.callback(result), // fix
CompletionType::Truncate(t) => t.callback(result),
};
self.inner
.result
.set(result.err())
.expect("result must be set only once");
});
}
/// only call this method if you are sure that the completion is
/// a ReadCompletion, panics otherwise
pub fn as_read(&self) -> &ReadCompletion {