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}