jpegxl_sys/threads/
parallel_runner.rs

1/*
2This file is part of jpegxl-sys.
3
4jpegxl-sys is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 3 of the License, or
7(at your option) any later version.
8
9jpegxl-sys is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with jpegxl-sys.  If not, see <https://www.gnu.org/licenses/>.
16*/
17
18//! API for running data operations in parallel in a multi-threaded environment.
19//! This module allows the JPEG XL caller to define their own way of creating and
20//! assigning threads.
21//!
22//! The [`JxlParallelRunner`] function type defines a parallel data processing
23//! runner that may be implemented by the caller to allow the library to process
24//! in multiple threads. The multi-threaded processing in this library only
25//! requires to run the same function over each number of a range, possibly
26//! running each call in a different thread. The JPEG XL caller is responsible
27//! for implementing this logic using the thread APIs available in their system.
28//! For convenience, a C++ implementation based on `std::thread` is provided in
29//! [`super::thread_parallel_runner`] (part of the `jpegxl_threads` library).
30//!
31//! Thread pools usually store small numbers of heterogeneous tasks in a queue.
32//! When tasks are identical or differ only by an integer input parameter, it is
33//! much faster to store just one function of an integer parameter and call it
34//! for each value. Conventional vector-of-tasks can be run in parallel using a
35//! lambda function adapter that simply calls `task_funcs[task]`.
36//!
37//! If no multi-threading is desired, a `NULL` value of [`JxlParallelRunner`]
38//! will use an internal implementation without multi-threading.
39
40use std::ffi::{c_int, c_void};
41
42/// Return code used in the `JxlParallel*` functions as return value. A value
43/// of [`JXL_PARALLEL_RET_SUCCESS`] means success and any other value means error.
44/// The special value [`JXL_PARALLEL_RET_RUNNER_ERROR`] can be used by the runner
45/// to indicate any other error.
46pub type JxlParallelRetCode = c_int;
47
48/// Code returned by the [`JxlParallelRunInit`] function to indicate success.
49pub const JXL_PARALLEL_RET_SUCCESS: JxlParallelRetCode = 0;
50
51/// Code returned by the [`JxlParallelRunInit`] function to indicate a general error.
52pub const JXL_PARALLEL_RET_RUNNER_ERROR: JxlParallelRetCode = -1;
53
54/// Parallel run initialization callback. See [`JxlParallelRunner`] for details.
55///
56/// This function MUST be called by the [`JxlParallelRunner`] only once, on the
57/// same thread that called [`JxlParallelRunner`], before any parallel
58/// execution. The purpose of this call is to provide the maximum number of
59/// threads that the [`JxlParallelRunner`] will use, which can be used by JPEG XL
60/// to allocate per-thread storage if needed.
61///
62/// # Parameters
63/// - `jpegxl_opaque`: the `jpegxl_opaque` handle provided to
64///   [`JxlParallelRunner`] must be passed here.
65/// - `num_threads`: the maximum number of threads. This value must be
66///   positive.
67///
68/// # Returns
69/// - `0` if the initialization process was successful.
70/// - An error code if there was an error, which should be returned by
71///   [`JxlParallelRunner`].
72pub type JxlParallelRunInit = unsafe extern "C-unwind" fn(
73    jpegxl_opaque: *mut c_void,
74    num_threads: usize,
75) -> JxlParallelRetCode;
76
77/// Parallel run data processing callback. See [`JxlParallelRunner`] for
78/// details.
79///
80/// This function MUST be called once for every number in the range `[start_range,
81/// end_range)` (including `start_range` but not including `end_range`) passing this
82/// number as the `value`. Calls for different values may be executed from
83/// different threads in parallel.
84///
85/// # Parameters
86/// - `jpegxl_opaque`: the `jpegxl_opaque` handle provided to
87///   [`JxlParallelRunner`] must be passed here.
88/// - `value`: the number in the range `[start_range, end_range)` of the call.
89/// - `thread_id`: the thread number where this function is being called from.
90///   This must be lower than the `num_threads` value passed to
91///   [`JxlParallelRunInit`].
92pub type JxlParallelRunFunction =
93    unsafe extern "C-unwind" fn(jpegxl_opaque: *mut c_void, value: u32, thread_id: usize);
94
95/// [`JxlParallelRunner`] function type. A parallel runner implementation can be
96/// provided by a JPEG XL caller to allow running computations in multiple
97/// threads. This function must call the initialization function [`init`](JxlParallelRunInit) in the
98/// same thread that called it and then call the passed [`func`](JxlParallelRunFunction) once for every
99/// number in the range `[start_range, end_range)` (including `start_range` but not
100/// including `end_range`) possibly from different multiple threads in parallel.
101///
102/// The [`JxlParallelRunner`] function does not need to be re-entrant. This
103/// means that the same [`JxlParallelRunner`] function with the same
104/// `runner_opaque` provided parameter will not be called from the library from
105/// either [`init`](JxlParallelRunInit) or [`func`](JxlParallelRunFunction) in the same decoder or encoder instance.
106/// However, a single decoding or encoding instance may call the provided [`JxlParallelRunner`] multiple
107/// times for different parts of the decoding or encoding process.
108///
109/// # Returns
110/// - `0`: if the [`init`](JxlParallelRunInit) call succeeded (returned `0`) and no other error
111///   occurred in the runner code.
112/// - [`JXL_PARALLEL_RET_RUNNER_ERROR`]: if an error occurred in the runner
113///   code, for example, setting up the threads.
114/// - The return value of [`init()`](JxlParallelRunInit) if non-zero.
115pub type JxlParallelRunner = unsafe extern "C-unwind" fn(
116    runner_opaque: *mut c_void,
117    jpegxl_opaque: *mut c_void,
118    init: JxlParallelRunInit,
119    func: JxlParallelRunFunction,
120    start_range: u32,
121    end_range: u32,
122) -> JxlParallelRetCode;