Skip to content

Commit f0ee8e2

Browse files
committed
add TTL Wrapper for common Functional Interface #162
1 parent b914539 commit f0ee8e2

File tree

3 files changed

+295
-0
lines changed

3 files changed

+295
-0
lines changed

src/main/java/com/alibaba/ttl/TtlCallable.java

+3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@
2020
* and transmit it to the time of {@link Callable} execution, needed when use {@link Callable} to thread pool.
2121
* <p>
2222
* Use factory method {@link #get(Callable)} to get decorated instance.
23+
* <p>
24+
* Other TTL Wrapper for common {@code Functional Interface} see {@link TtlWrappers}.
2325
*
2426
* @author Jerry Lee (oldratlee at gmail dot com)
2527
* @see com.alibaba.ttl.threadpool.TtlExecutors
28+
* @see TtlWrappers
2629
* @see java.util.concurrent.Executor
2730
* @see java.util.concurrent.ExecutorService
2831
* @see java.util.concurrent.ThreadPoolExecutor

src/main/java/com/alibaba/ttl/TtlRunnable.java

+3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919
* and transmit it to the time of {@link Runnable} execution, needed when use {@link Runnable} to thread pool.
2020
* <p>
2121
* Use factory methods {@link #get} / {@link #gets} to create instance.
22+
* <p>
23+
* Other TTL Wrapper for common {@code Functional Interface} see {@link TtlWrappers}.
2224
*
2325
* @author Jerry Lee (oldratlee at gmail dot com)
2426
* @see com.alibaba.ttl.threadpool.TtlExecutors
27+
* @see TtlWrappers
2528
* @see java.util.concurrent.Executor
2629
* @see java.util.concurrent.ExecutorService
2730
* @see java.util.concurrent.ThreadPoolExecutor
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
package com.alibaba.ttl;
2+
3+
import com.alibaba.ttl.spi.TtlEnhanced;
4+
import edu.umd.cs.findbugs.annotations.NonNull;
5+
import edu.umd.cs.findbugs.annotations.Nullable;
6+
7+
import java.util.concurrent.Callable;
8+
import java.util.function.*;
9+
10+
import static com.alibaba.ttl.TransmittableThreadLocal.Transmitter.*;
11+
12+
/**
13+
* Util methods for TTL Wrapper for common {@code Functional Interface}.
14+
* <p>
15+
* <b><i>Note:</i></b>
16+
* <ul>
17+
* <li>all method is {@code null}-safe, when input parameter is {@code null}, return {@code null}.</li>
18+
* <li>skip wrap (aka. just return input parameter), when input parameter is already wrapped.</li>
19+
* </ul>
20+
*
21+
* @author Jerry Lee (oldratlee at gmail dot com)
22+
* @see TtlRunnable
23+
* @see TtlRunnable#get(Runnable)
24+
* @see TtlRunnable#unwrap(Runnable)
25+
* @see TtlCallable
26+
* @see TtlCallable#get(Callable)
27+
* @see TtlCallable#unwrap(Callable)
28+
* @since 2.11.4
29+
*/
30+
public class TtlWrappers {
31+
/**
32+
* wrap input {@link Supplier} to TTL wrapper.
33+
*
34+
* @param supplier input {@link Supplier}
35+
* @return Wrapped {@link Supplier}
36+
* @since 2.11.4
37+
*/
38+
@Nullable
39+
public static <T> Supplier<T> wrap(@Nullable Supplier<T> supplier) {
40+
if (supplier == null) return null;
41+
else if (supplier instanceof TtlEnhanced) return supplier;
42+
else return new TtlSupplier<T>(supplier);
43+
}
44+
45+
private static class TtlSupplier<T> implements Supplier<T>, TtlEnhanced {
46+
final Supplier<T> supplier;
47+
final Object capture;
48+
49+
TtlSupplier(@NonNull Supplier<T> supplier) {
50+
this.supplier = supplier;
51+
this.capture = capture();
52+
}
53+
54+
@Override
55+
public T get() {
56+
final Object backup = replay(capture);
57+
try {
58+
return supplier.get();
59+
} finally {
60+
restore(backup);
61+
}
62+
}
63+
}
64+
65+
/**
66+
* Unwrap {@code TtlSupplier} to the original/underneath one.
67+
* <p>
68+
* this method is {@code null}-safe, when input {@code Supplier} parameter is {@code null}, return {@code null};
69+
* if input {@code Supplier} parameter is not a {@code Supplier} just return input {@code Supplier}.
70+
* <p>
71+
* so {@code unwrap(Supplier)} will always return the same input {@code Supplier} object.
72+
*
73+
* @see #wrap(Supplier)
74+
* @since 2.11.4
75+
*/
76+
@Nullable
77+
public static <T> Supplier<T> unwrap(@Nullable Supplier<T> supplier) {
78+
if (!(supplier instanceof TtlSupplier)) return supplier;
79+
else return ((TtlSupplier<T>) supplier).supplier;
80+
}
81+
82+
/**
83+
* wrap input {@link Consumer} to TTL wrapper.
84+
*
85+
* @param consumer input {@link Consumer}
86+
* @return Wrapped {@link Consumer}
87+
* @since 2.11.4
88+
*/
89+
@Nullable
90+
public static <T> Consumer<T> wrap(@Nullable Consumer<T> consumer) {
91+
if (consumer == null) return null;
92+
else if (consumer instanceof TtlEnhanced) return consumer;
93+
else return new TtlConsumer<T>(consumer);
94+
}
95+
96+
private static class TtlConsumer<T> implements Consumer<T>, TtlEnhanced {
97+
final Consumer<T> consumer;
98+
final Object capture;
99+
100+
TtlConsumer(@NonNull Consumer<T> consumer) {
101+
this.consumer = consumer;
102+
this.capture = capture();
103+
}
104+
105+
@Override
106+
public void accept(T t) {
107+
final Object backup = replay(capture);
108+
try {
109+
consumer.accept(t);
110+
} finally {
111+
restore(backup);
112+
}
113+
}
114+
}
115+
116+
/**
117+
* Unwrap {@code TtlConsumer} to the original/underneath one.
118+
* <p>
119+
* this method is {@code null}-safe, when input {@code Consumer} parameter is {@code null}, return {@code null};
120+
* if input {@code Consumer} parameter is not a {@code Consumer} just return input {@code Consumer}.
121+
* <p>
122+
* so {@code unwrap(Consumer)} will always return the same input {@code Consumer} object.
123+
*
124+
* @see #wrap(Consumer)
125+
* @since 2.11.4
126+
*/
127+
@Nullable
128+
public static <T> Consumer<T> unwrap(@Nullable Consumer<T> consumer) {
129+
if (!(consumer instanceof TtlConsumer)) return consumer;
130+
else return ((TtlConsumer<T>) consumer).consumer;
131+
}
132+
133+
/**
134+
* wrap input {@link BiConsumer} to TTL wrapper.
135+
*
136+
* @param consumer input {@link BiConsumer}
137+
* @return Wrapped {@link BiConsumer}
138+
* @since 2.11.4
139+
*/
140+
@Nullable
141+
public static <T, U> BiConsumer<T, U> wrap(@Nullable BiConsumer<T, U> consumer) {
142+
if (consumer == null) return null;
143+
else if (consumer instanceof TtlEnhanced) return consumer;
144+
else return new TtlBiConsumer<T, U>(consumer);
145+
}
146+
147+
private static class TtlBiConsumer<T, U> implements BiConsumer<T, U>, TtlEnhanced {
148+
final BiConsumer<T, U> consumer;
149+
final Object capture;
150+
151+
TtlBiConsumer(@NonNull BiConsumer<T, U> consumer) {
152+
this.consumer = consumer;
153+
this.capture = capture();
154+
}
155+
156+
@Override
157+
public void accept(T t, U u) {
158+
final Object backup = replay(capture);
159+
try {
160+
consumer.accept(t, u);
161+
} finally {
162+
restore(backup);
163+
}
164+
}
165+
}
166+
167+
/**
168+
* Unwrap {@code TtlBiConsumer} to the original/underneath one.
169+
* <p>
170+
* this method is {@code null}-safe, when input {@code BiConsumer} parameter is {@code null}, return {@code null};
171+
* if input {@code BiConsumer} parameter is not a {@code BiConsumer} just return input {@code BiConsumer}.
172+
* <p>
173+
* so {@code unwrap(BiConsumer)} will always return the same input {@code BiConsumer} object.
174+
*
175+
* @see #wrap(BiConsumer)
176+
* @since 2.11.4
177+
*/
178+
@Nullable
179+
public static <T, U> BiConsumer<T, U> unwrap(@Nullable BiConsumer<T, U> consumer) {
180+
if (!(consumer instanceof TtlBiConsumer)) return consumer;
181+
else return ((TtlBiConsumer<T, U>) consumer).consumer;
182+
}
183+
184+
/**
185+
* wrap input {@link Function} to TTL wrapper.
186+
*
187+
* @param fn input {@link Function}
188+
* @return Wrapped {@link Function}
189+
* @since 2.11.4
190+
*/
191+
@Nullable
192+
public static <T, R> Function<T, R> wrap(@Nullable Function<T, R> fn) {
193+
if (fn == null) return null;
194+
else if (fn instanceof TtlEnhanced) return fn;
195+
else return new TtlFunction<T, R>(fn);
196+
}
197+
198+
private static class TtlFunction<T, R> implements Function<T, R>, TtlEnhanced {
199+
final Function<T, R> fn;
200+
final Object capture;
201+
202+
TtlFunction(@NonNull Function<T, R> fn) {
203+
this.fn = fn;
204+
this.capture = capture();
205+
}
206+
207+
@Override
208+
public R apply(T t) {
209+
final Object backup = replay(capture);
210+
try {
211+
return fn.apply(t);
212+
} finally {
213+
restore(backup);
214+
}
215+
}
216+
}
217+
218+
/**
219+
* Unwrap {@code TtlFunction} to the original/underneath one.
220+
* <p>
221+
* this method is {@code null}-safe, when input {@code Function} parameter is {@code null}, return {@code null};
222+
* if input {@code Function} parameter is not a {@code TtlFunction} just return input {@code Function}.
223+
* <p>
224+
* so {@code unwrap(Function)} will always return the same input {@code Function} object.
225+
*
226+
* @see #wrap(Function)
227+
* @since 2.11.4
228+
*/
229+
@Nullable
230+
public static <T, R> Function<T, R> unwrap(@Nullable Function<T, R> fn) {
231+
if (!(fn instanceof TtlFunction)) return fn;
232+
else return ((TtlFunction<T, R>) fn).fn;
233+
}
234+
235+
/**
236+
* wrap input {@link BiFunction} to TTL wrapper.
237+
*
238+
* @param fn input {@link BiFunction}
239+
* @return Wrapped {@link BiFunction}
240+
* @since 2.11.4
241+
*/
242+
@Nullable
243+
public static <T, U, R> BiFunction<T, U, R> wrap(@Nullable BiFunction<T, U, R> fn) {
244+
if (fn == null) return null;
245+
else if (fn instanceof TtlEnhanced) return fn;
246+
else return new TtlBiFunction<T, U, R>(fn);
247+
}
248+
249+
private static class TtlBiFunction<T, U, R> implements BiFunction<T, U, R>, TtlEnhanced {
250+
final BiFunction<T, U, R> fn;
251+
final Object capture;
252+
253+
TtlBiFunction(@NonNull BiFunction<T, U, R> fn) {
254+
this.fn = fn;
255+
this.capture = capture();
256+
}
257+
258+
@Override
259+
public R apply(T t, U u) {
260+
final Object backup = replay(capture);
261+
try {
262+
return fn.apply(t, u);
263+
} finally {
264+
restore(backup);
265+
}
266+
}
267+
}
268+
269+
/**
270+
* Unwrap {@code TtlBiFunction} to the original/underneath one.
271+
* <p>
272+
* this method is {@code null}-safe, when input {@code BiFunction} parameter is {@code null}, return {@code null};
273+
* if input {@code BiFunction} parameter is not a {@code TtlBiFunction} just return input {@code BiFunction}.
274+
* <p>
275+
* so {@code unwrap(BiFunction)} will always return the same input {@code BiFunction} object.
276+
*
277+
* @see #wrap(BiFunction)
278+
* @since 2.11.4
279+
*/
280+
@Nullable
281+
public static <T, U, R> BiFunction<T, U, R> unwrap(@Nullable BiFunction<T, U, R> fn) {
282+
if (!(fn instanceof TtlBiFunction)) return fn;
283+
else return ((TtlBiFunction<T, U, R>) fn).fn;
284+
}
285+
286+
private TtlWrappers() {
287+
throw new InstantiationError("Must not instantiate this class");
288+
}
289+
}

0 commit comments

Comments
 (0)