brotli/enc/
singlethreading.rs

1use alloc::{Allocator, SliceWrapper};
2use core::marker::PhantomData;
3use core::mem;
4#[cfg(feature = "std")]
5use std;
6
7use super::backward_references::UnionHasher;
8use crate::enc::threading::{
9    BatchSpawnable, BatchSpawnableLite, BrotliEncoderThreadError, CompressMulti,
10    CompressionThreadResult, InternalOwned, InternalSendAlloc, Joinable, Owned, OwnedRetriever,
11    PoisonedThreadError, SendAlloc,
12};
13use crate::enc::{BrotliAlloc, BrotliEncoderParams};
14
15pub struct SingleThreadedJoinable<T: Send + 'static, U: Send + 'static> {
16    result: Result<T, U>,
17}
18impl<T: Send + 'static, U: Send + 'static> Joinable<T, U> for SingleThreadedJoinable<T, U> {
19    fn join(self) -> Result<T, U> {
20        self.result
21    }
22}
23#[cfg(feature = "std")]
24pub struct SingleThreadedOwnedRetriever<U: Send + 'static>(std::sync::RwLock<U>);
25#[cfg(feature = "std")]
26impl<U: Send + 'static> OwnedRetriever<U> for SingleThreadedOwnedRetriever<U> {
27    fn view<T, F: FnOnce(&U) -> T>(&self, f: F) -> Result<T, PoisonedThreadError> {
28        Ok(f(&*self.0.read().unwrap()))
29    }
30    fn unwrap(self) -> Result<U, PoisonedThreadError> {
31        Ok(self.0.into_inner().unwrap())
32    }
33}
34#[cfg(feature = "std")]
35impl<U: Send + 'static> SingleThreadedOwnedRetriever<U> {
36    fn new(u: U) -> Self {
37        SingleThreadedOwnedRetriever(std::sync::RwLock::new(u))
38    }
39}
40
41#[cfg(not(feature = "std"))]
42pub struct SingleThreadedOwnedRetriever<U: Send + 'static>(U);
43#[cfg(not(feature = "std"))]
44impl<U: Send + 'static> SingleThreadedOwnedRetriever<U> {
45    fn new(u: U) -> Self {
46        SingleThreadedOwnedRetriever(u)
47    }
48}
49#[cfg(not(feature = "std"))]
50impl<U: Send + 'static> OwnedRetriever<U> for SingleThreadedOwnedRetriever<U> {
51    fn view<T, F: FnOnce(&U) -> T>(&self, f: F) -> Result<T, PoisonedThreadError> {
52        Ok(f(&self.0))
53    }
54    fn unwrap(self) -> Result<U, PoisonedThreadError> {
55        Ok(self.0)
56    }
57}
58
59#[derive(Default)]
60pub struct SingleThreadedSpawner {}
61
62impl<
63        ReturnValue: Send + 'static,
64        ExtraInput: Send + 'static,
65        Alloc: BrotliAlloc + Send + 'static,
66        U: Send + 'static + Sync,
67    > BatchSpawnable<ReturnValue, ExtraInput, Alloc, U> for SingleThreadedSpawner
68where
69    <Alloc as Allocator<u8>>::AllocatedMemory: Send + 'static,
70{
71    type JoinHandle = SingleThreadedJoinable<ReturnValue, BrotliEncoderThreadError>;
72    type FinalJoinHandle = SingleThreadedOwnedRetriever<U>;
73    fn make_spawner(&mut self, input: &mut Owned<U>) -> Self::FinalJoinHandle {
74        SingleThreadedOwnedRetriever::<U>::new(
75            mem::replace(input, Owned(InternalOwned::Borrowed)).unwrap(),
76        )
77    }
78    fn spawn<F: Fn(ExtraInput, usize, usize, &U, Alloc) -> ReturnValue + Send + 'static + Copy>(
79        &mut self,
80        handle: &mut Self::FinalJoinHandle,
81        work: &mut SendAlloc<ReturnValue, ExtraInput, Alloc, Self::JoinHandle>,
82        index: usize,
83        num_threads: usize,
84        f: F,
85    ) {
86        let (alloc, extra_input) = work.replace_with_default();
87        let ret = handle.view(|sub_view| f(extra_input, index, num_threads, sub_view, alloc));
88        *work = SendAlloc(InternalSendAlloc::Join(SingleThreadedJoinable {
89            result: Ok(ret.unwrap()),
90        }));
91    }
92}
93
94impl<
95        ReturnValue: Send + 'static,
96        ExtraInput: Send + 'static,
97        Alloc: BrotliAlloc + Send + 'static,
98        U: Send + 'static + Sync,
99    > BatchSpawnableLite<ReturnValue, ExtraInput, Alloc, U> for SingleThreadedSpawner
100where
101    <Alloc as Allocator<u8>>::AllocatedMemory: Send + 'static,
102{
103    type JoinHandle =
104        <SingleThreadedSpawner as BatchSpawnable<ReturnValue, ExtraInput, Alloc, U>>::JoinHandle;
105    type FinalJoinHandle = <SingleThreadedSpawner as BatchSpawnable<
106        ReturnValue,
107        ExtraInput,
108        Alloc,
109        U,
110    >>::FinalJoinHandle;
111
112    fn make_spawner(&mut self, input: &mut Owned<U>) -> Self::FinalJoinHandle {
113        <Self as BatchSpawnable<ReturnValue, ExtraInput, Alloc, U>>::make_spawner(self, input)
114    }
115    fn spawn(
116        &mut self,
117        handle: &mut Self::FinalJoinHandle,
118        alloc_per_thread: &mut SendAlloc<ReturnValue, ExtraInput, Alloc, Self::JoinHandle>,
119        index: usize,
120        num_threads: usize,
121        f: fn(ExtraInput, usize, usize, &U, Alloc) -> ReturnValue,
122    ) {
123        <Self as BatchSpawnable<ReturnValue, ExtraInput, Alloc, U>>::spawn(
124            self,
125            handle,
126            alloc_per_thread,
127            index,
128            num_threads,
129            f,
130        )
131    }
132}
133
134pub fn compress_multi<
135    Alloc: BrotliAlloc + Send + 'static,
136    SliceW: SliceWrapper<u8> + Send + 'static + Sync,
137>(
138    params: &BrotliEncoderParams,
139    owned_input: &mut Owned<SliceW>,
140    output: &mut [u8],
141    alloc_per_thread: &mut [SendAlloc<
142        CompressionThreadResult<Alloc>,
143        UnionHasher<Alloc>,
144        Alloc,
145        <SingleThreadedSpawner as BatchSpawnable<
146            CompressionThreadResult<Alloc>,
147            UnionHasher<Alloc>,
148            Alloc,
149            SliceW,
150        >>::JoinHandle,
151    >],
152) -> Result<usize, BrotliEncoderThreadError>
153where
154    <Alloc as Allocator<u8>>::AllocatedMemory: Send,
155    <Alloc as Allocator<u16>>::AllocatedMemory: Send,
156    <Alloc as Allocator<u32>>::AllocatedMemory: Send,
157{
158    CompressMulti(
159        params,
160        owned_input,
161        output,
162        alloc_per_thread,
163        &mut SingleThreadedSpawner::default(),
164    )
165}
166
167pub struct WorkerPool<A, B, C, D> {
168    a: PhantomData<A>,
169    b: PhantomData<B>,
170    c: PhantomData<C>,
171    d: PhantomData<D>,
172}
173pub fn new_work_pool<A, B, C, D>(_num_threads: usize) -> WorkerPool<A, B, C, D> {
174    WorkerPool::<A, B, C, D> {
175        a: PhantomData,
176        b: PhantomData,
177        c: PhantomData,
178        d: PhantomData,
179    }
180}
181
182pub fn compress_worker_pool<
183    Alloc: BrotliAlloc + Send + 'static,
184    SliceW: SliceWrapper<u8> + Send + 'static + Sync,
185>(
186    params: &BrotliEncoderParams,
187    owned_input: &mut Owned<SliceW>,
188    output: &mut [u8],
189    alloc_per_thread: &mut [SendAlloc<
190        CompressionThreadResult<Alloc>,
191        UnionHasher<Alloc>,
192        Alloc,
193        <SingleThreadedSpawner as BatchSpawnable<
194            CompressionThreadResult<Alloc>,
195            UnionHasher<Alloc>,
196            Alloc,
197            SliceW,
198        >>::JoinHandle,
199    >],
200    _worker_pool: &mut WorkerPool<
201        CompressionThreadResult<Alloc>,
202        UnionHasher<Alloc>,
203        Alloc,
204        (SliceW, BrotliEncoderParams),
205    >,
206) -> Result<usize, BrotliEncoderThreadError>
207where
208    <Alloc as Allocator<u8>>::AllocatedMemory: Send,
209    <Alloc as Allocator<u16>>::AllocatedMemory: Send,
210    <Alloc as Allocator<u32>>::AllocatedMemory: Send,
211{
212    compress_multi(params, owned_input, output, alloc_per_thread)
213}