refactor(mt): move terminal frame action policy to Rust

Classify the MT terminal-job flags in Rust while retaining the two private C
mutations as narrow callbacks. Descriptor setup, reusable-input reset, and
terminal frame publication keep their original order; nonterminal jobs remain
untouched, and checksum clearing still occurs only for the original flag
combination.

Test Plan:
- `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings` -- passed
- `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings` -- passed
- `ulimit -v 41943040; cargo +nightly fmt --manifest-path rust/Cargo.toml --all -- --check` -- passed
- `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/cli/Cargo.toml --all-targets` -- passed, 190 tests
- `ulimit -v 41943040; CARGO_BUILD_JOBS=1 make -j1` -- passed
- `ulimit -v 41943040; CARGO_BUILD_JOBS=1 ./tests/rustLibSmoke` -- passed
- `ulimit -v 41943040; CARGO_BUILD_JOBS=1 make -j1 -C tests test` -- passed, including large streaming, native, fuzzer, and zstream phases
This commit is contained in:
2026-07-20 19:29:23 +02:00
parent bab90f3622
commit e9850abbb7
2 changed files with 100 additions and 30 deletions
+13 -11
View File
@@ -545,6 +545,7 @@ enum {
}; };
typedef void (*ZSTDMT_prepareJobFn)(void* opaque, unsigned jobID, typedef void (*ZSTDMT_prepareJobFn)(void* opaque, unsigned jobID,
const ZSTDMT_RustJobInitialization* init); const ZSTDMT_RustJobInitialization* init);
typedef void (*ZSTDMT_prepareFrameStateFn)(void* opaque);
typedef void (*ZSTDMT_writeEmptyJobFn)(void* opaque, unsigned jobID); typedef void (*ZSTDMT_writeEmptyJobFn)(void* opaque, unsigned jobID);
typedef int (*ZSTDMT_tryAddJobFn)(void* opaque, unsigned jobID); typedef int (*ZSTDMT_tryAddJobFn)(void* opaque, unsigned jobID);
void ZSTDMT_rust_prepareCompressionJob( void ZSTDMT_rust_prepareCompressionJob(
@@ -552,7 +553,8 @@ void ZSTDMT_rust_prepareCompressionJob(
const ZSTDMT_RustJobInitialization* initialization, const ZSTDMT_RustJobInitialization* initialization,
ZSTDMT_prepareJobFn initializeJob, ZSTDMT_prepareJobFn initializeJob,
ZSTDMT_prepareJobFn resetInputState, ZSTDMT_prepareJobFn resetInputState,
ZSTDMT_prepareJobFn publishFrameState); ZSTDMT_prepareFrameStateFn setFrameEnded,
ZSTDMT_prepareFrameStateFn clearChecksumFlag);
ZSTDMT_RustCreateJobResult ZSTDMT_rust_createCompressionJob( ZSTDMT_RustCreateJobResult ZSTDMT_rust_createCompressionJob(
const ZSTDMT_RustCreateJobProjection* projection, const ZSTDMT_RustCreateJobProjection* projection,
void* opaque, ZSTDMT_prepareJobFn prepareJob, void* opaque, ZSTDMT_prepareJobFn prepareJob,
@@ -2931,17 +2933,16 @@ static void ZSTDMT_prepareCompressionJobInputState(
}; };
} }
static void ZSTDMT_prepareCompressionJobFrameState( static void ZSTDMT_prepareCompressionJobSetFrameEnded(void* opaque)
void* opaque, unsigned jobID,
const ZSTDMT_RustJobInitialization* initialization)
{ {
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque; ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
(void)jobID; mtctx->frameEnded = 1;
if (initialization->lastJob) { }
mtctx->frameEnded = 1;
if (initialization->clearChecksumFlag) static void ZSTDMT_prepareCompressionJobClearChecksumFlag(void* opaque)
mtctx->params.fParams.checksumFlag = 0; {
} ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
mtctx->params.fParams.checksumFlag = 0;
} }
static void ZSTDMT_prepareCompressionJob( static void ZSTDMT_prepareCompressionJob(
@@ -2952,7 +2953,8 @@ static void ZSTDMT_prepareCompressionJob(
opaque, jobID, initialization, opaque, jobID, initialization,
ZSTDMT_prepareCompressionJobDescriptor, ZSTDMT_prepareCompressionJobDescriptor,
ZSTDMT_prepareCompressionJobInputState, ZSTDMT_prepareCompressionJobInputState,
ZSTDMT_prepareCompressionJobFrameState); ZSTDMT_prepareCompressionJobSetFrameEnded,
ZSTDMT_prepareCompressionJobClearChecksumFlag);
} }
static void ZSTDMT_writeEmptyCompressionJob(void* opaque, unsigned jobID) static void ZSTDMT_writeEmptyCompressionJob(void* opaque, unsigned jobID)
+87 -19
View File
@@ -1544,30 +1544,65 @@ pub type ZSTDMT_prepareJobFn = unsafe extern "C" fn(
job_id: c_uint, job_id: c_uint,
initialization: *const ZSTDMT_jobInitialization, initialization: *const ZSTDMT_jobInitialization,
); );
pub type ZSTDMT_prepareFrameStateFn = unsafe extern "C" fn(opaque: *mut c_void);
pub type ZSTDMT_writeEmptyJobFn = unsafe extern "C" fn(opaque: *mut c_void, job_id: c_uint); pub type ZSTDMT_writeEmptyJobFn = unsafe extern "C" fn(opaque: *mut c_void, job_id: c_uint);
pub type ZSTDMT_tryAddJobFn = unsafe extern "C" fn(opaque: *mut c_void, job_id: c_uint) -> c_int; pub type ZSTDMT_tryAddJobFn = unsafe extern "C" fn(opaque: *mut c_void, job_id: c_uint) -> c_int;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum CompressionJobFrameStateAction {
None,
SetFrameEnded,
SetFrameEndedAndClearChecksum,
}
#[inline]
fn classify_compression_job_frame_state(
last_job: c_uint,
clear_checksum_flag: c_uint,
) -> CompressionJobFrameStateAction {
if last_job == 0 {
CompressionJobFrameStateAction::None
} else if clear_checksum_flag == 0 {
CompressionJobFrameStateAction::SetFrameEnded
} else {
CompressionJobFrameStateAction::SetFrameEndedAndClearChecksum
}
}
/// Order the C-owned leaves that publish a newly prepared MT job. /// Order the C-owned leaves that publish a newly prepared MT job.
/// ///
/// The descriptor must become complete before the reusable input range is /// The descriptor must become complete before the reusable input range is
/// cleared, and terminal frame state is published last. `lastJob` is a C /// cleared, and terminal frame state is published last. `lastJob` and
/// boolean scalar, so any non-zero value selects the terminal publication. /// `clearChecksumFlag` are classified in Rust; C callbacks retain the private
/// context mutations.
#[inline] #[inline]
fn prepare_compression_job_with<P, I, F>( fn prepare_compression_job_with<P, I, S, C>(
job_id: c_uint, job_id: c_uint,
initialization: &ZSTDMT_jobInitialization, initialization: &ZSTDMT_jobInitialization,
mut initialize_job: P, mut initialize_job: P,
mut reset_input_state: I, mut reset_input_state: I,
mut publish_frame_state: F, mut set_frame_ended: S,
mut clear_checksum_flag: C,
) where ) where
P: FnMut(c_uint, &ZSTDMT_jobInitialization), P: FnMut(c_uint, &ZSTDMT_jobInitialization),
I: FnMut(c_uint, &ZSTDMT_jobInitialization), I: FnMut(c_uint, &ZSTDMT_jobInitialization),
F: FnMut(c_uint, &ZSTDMT_jobInitialization), S: FnMut(),
C: FnMut(),
{ {
let frame_state_action = classify_compression_job_frame_state(
initialization.lastJob,
initialization.clearChecksumFlag,
);
initialize_job(job_id, initialization); initialize_job(job_id, initialization);
reset_input_state(job_id, initialization); reset_input_state(job_id, initialization);
if initialization.lastJob != 0 { match frame_state_action {
publish_frame_state(job_id, initialization); CompressionJobFrameStateAction::None => {}
CompressionJobFrameStateAction::SetFrameEnded => set_frame_ended(),
CompressionJobFrameStateAction::SetFrameEndedAndClearChecksum => {
set_frame_ended();
clear_checksum_flag();
}
} }
} }
@@ -1580,13 +1615,23 @@ pub unsafe extern "C" fn ZSTDMT_rust_prepareCompressionJob(
initialization: *const ZSTDMT_jobInitialization, initialization: *const ZSTDMT_jobInitialization,
initialize_job: Option<ZSTDMT_prepareJobFn>, initialize_job: Option<ZSTDMT_prepareJobFn>,
reset_input_state: Option<ZSTDMT_prepareJobFn>, reset_input_state: Option<ZSTDMT_prepareJobFn>,
publish_frame_state: Option<ZSTDMT_prepareJobFn>, set_frame_ended: Option<ZSTDMT_prepareFrameStateFn>,
clear_checksum_flag: Option<ZSTDMT_prepareFrameStateFn>,
) { ) {
let Some(initialization) = (unsafe { initialization.as_ref() }) else { let Some(initialization) = (unsafe { initialization.as_ref() }) else {
return; return;
}; };
let (Some(initialize_job), Some(reset_input_state), Some(publish_frame_state)) = let (
(initialize_job, reset_input_state, publish_frame_state) Some(initialize_job),
Some(reset_input_state),
Some(set_frame_ended),
Some(clear_checksum_flag),
) = (
initialize_job,
reset_input_state,
set_frame_ended,
clear_checksum_flag,
)
else { else {
return; return;
}; };
@@ -1603,8 +1648,11 @@ pub unsafe extern "C" fn ZSTDMT_rust_prepareCompressionJob(
|job_id, initialization| unsafe { |job_id, initialization| unsafe {
reset_input_state(opaque, job_id, initialization); reset_input_state(opaque, job_id, initialization);
}, },
|job_id, initialization| unsafe { || unsafe {
publish_frame_state(opaque, job_id, initialization); set_frame_ended(opaque);
},
|| unsafe {
clear_checksum_flag(opaque);
}, },
); );
} }
@@ -7125,6 +7173,25 @@ mod tests {
assert_eq!(result.jobReady, 0); assert_eq!(result.jobReady, 0);
} }
#[test]
fn compression_job_frame_state_classifies_all_flag_combinations() {
for (last_job, clear_checksum_flag, expected) in [
(0, 0, CompressionJobFrameStateAction::None),
(0, 1, CompressionJobFrameStateAction::None),
(1, 0, CompressionJobFrameStateAction::SetFrameEnded),
(
1,
1,
CompressionJobFrameStateAction::SetFrameEndedAndClearChecksum,
),
] {
assert_eq!(
classify_compression_job_frame_state(last_job, clear_checksum_flag),
expected
);
}
}
#[test] #[test]
fn job_preparation_orders_descriptor_input_and_terminal_state() { fn job_preparation_orders_descriptor_input_and_terminal_state() {
let initialization = ZSTDMT_jobInitialization { let initialization = ZSTDMT_jobInitialization {
@@ -7148,14 +7215,14 @@ mod tests {
assert_eq!(value.roundBuffPosDelta, 0); assert_eq!(value.roundBuffPosDelta, 0);
events.borrow_mut().push("input"); events.borrow_mut().push("input");
}, },
|job_id, value| { || events.borrow_mut().push("frame-ended"),
assert_eq!(job_id, 3); || events.borrow_mut().push("checksum"),
assert_eq!(value.clearChecksumFlag, 1);
events.borrow_mut().push("frame");
},
); );
assert_eq!(events.into_inner(), vec!["descriptor", "input", "frame"]); assert_eq!(
events.into_inner(),
vec!["descriptor", "input", "frame-ended", "checksum"]
);
} }
#[test] #[test]
@@ -7168,7 +7235,8 @@ mod tests {
&initialization, &initialization,
|_job_id, _value| events.borrow_mut().push("descriptor"), |_job_id, _value| events.borrow_mut().push("descriptor"),
|_job_id, _value| events.borrow_mut().push("input"), |_job_id, _value| events.borrow_mut().push("input"),
|_job_id, _value| panic!("nonterminal job must not publish frame state"), || panic!("nonterminal job must not set frame-ended state"),
|| panic!("nonterminal job must not clear checksum state"),
); );
assert_eq!(events.into_inner(), vec!["descriptor", "input"]); assert_eq!(events.into_inner(), vec!["descriptor", "input"]);