Home | History | Annotate | Download | only in pooled
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.util.function.pooled;
     18 
     19 import static com.android.internal.util.function.pooled.PooledLambdaImpl.acquire;
     20 import static com.android.internal.util.function.pooled.PooledLambdaImpl.acquireConstSupplier;
     21 
     22 import android.os.Message;
     23 
     24 import com.android.internal.util.function.HexConsumer;
     25 import com.android.internal.util.function.HexFunction;
     26 import com.android.internal.util.function.QuadConsumer;
     27 import com.android.internal.util.function.QuadFunction;
     28 import com.android.internal.util.function.QuintConsumer;
     29 import com.android.internal.util.function.QuintFunction;
     30 import com.android.internal.util.function.TriConsumer;
     31 import com.android.internal.util.function.TriFunction;
     32 import com.android.internal.util.function.pooled.PooledLambdaImpl.LambdaType.ReturnType;
     33 
     34 import java.util.function.BiConsumer;
     35 import java.util.function.BiFunction;
     36 import java.util.function.BiPredicate;
     37 import java.util.function.Consumer;
     38 import java.util.function.Function;
     39 import java.util.function.Predicate;
     40 import java.util.function.Supplier;
     41 
     42 /**
     43  * A recyclable anonymous function.
     44  * Allows obtaining {@link Function}s/{@link Runnable}s/{@link Supplier}s/etc. without allocating a
     45  * new instance each time
     46  *
     47  * This exploits the mechanic that stateless lambdas (such as plain/non-bound method references)
     48  * get translated into a singleton instance, making it possible to create a recyclable container
     49  * ({@link PooledLambdaImpl}) holding a reference to such a singleton function, as well as
     50  * (possibly partial) arguments required for its invocation.
     51  *
     52  * To obtain an instance, use one of the factory methods in this class.
     53  *
     54  * You can call {@link #recycleOnUse} to make the instance automatically recycled upon invocation,
     55  * making if effectively <b>one-time use</b>.
     56  * This is often the behavior you want, as it allows to not worry about manual recycling.
     57  * Some notable examples: {@link android.os.Handler#post(Runnable)},
     58  * {@link android.app.Activity#runOnUiThread(Runnable)}, {@link android.view.View#post(Runnable)}
     59  *
     60  * For factories of functions that take further arguments, the corresponding 'missing' argument's
     61  * position is marked by an argument of type {@link ArgumentPlaceholder} with the type parameter
     62  * corresponding to missing argument's type.
     63  * You can fill the 'missing argument' spot with {@link #__()}
     64  * (which is the factory function for {@link ArgumentPlaceholder})
     65  *
     66  * NOTE: It is highly recommended to <b>only</b> use {@code ClassName::methodName}
     67  * (aka unbounded method references) as the 1st argument for any of the
     68  * factories ({@code obtain*(...)}) to avoid unwanted allocations.
     69  * This means <b>not</b> using:
     70  * <ul>
     71  *     <li>{@code someVar::methodName} or {@code this::methodName} as it captures the reference
     72  *     on the left of {@code ::}, resulting in an allocation on each evaluation of such
     73  *     bounded method references</li>
     74  *
     75  *     <li>A lambda expression, e.g. {@code () -> toString()} due to how easy it is to accidentally
     76  *     capture state from outside. In the above lambda expression for example, no variable from
     77  *     outer scope is explicitly mentioned, yet one is still captured due to {@code toString()}
     78  *     being an equivalent of {@code this.toString()}</li>
     79  * </ul>
     80  *
     81  * @hide
     82  */
     83 @SuppressWarnings({"unchecked", "unused", "WeakerAccess"})
     84 public interface PooledLambda {
     85 
     86     /**
     87      * Recycles this instance. No-op if already recycled.
     88      */
     89     void recycle();
     90 
     91     /**
     92      * Makes this instance automatically {@link #recycle} itself after the first call.
     93      *
     94      * @return this instance for convenience
     95      */
     96     PooledLambda recycleOnUse();
     97 
     98 
     99     // Factories
    100 
    101     /**
    102      * @return {@link ArgumentPlaceholder} with the inferred type parameter value
    103      */
    104     static <R> ArgumentPlaceholder<R> __() {
    105         return (ArgumentPlaceholder<R>) ArgumentPlaceholder.INSTANCE;
    106     }
    107 
    108     /**
    109      * @param typeHint the explicitly specified type of the missing argument
    110      * @return {@link ArgumentPlaceholder} with the specified type parameter value
    111      */
    112     static <R> ArgumentPlaceholder<R> __(Class<R> typeHint) {
    113         return __();
    114     }
    115 
    116     /**
    117      * Wraps the given value into a {@link PooledSupplier}
    118      *
    119      * @param value a value to wrap
    120      * @return a pooled supplier of {@code value}
    121      */
    122     static <R> PooledSupplier<R> obtainSupplier(R value) {
    123         PooledLambdaImpl r = acquireConstSupplier(ReturnType.OBJECT);
    124         r.mFunc = value;
    125         return r;
    126     }
    127 
    128     /**
    129      * Wraps the given value into a {@link PooledSupplier}
    130      *
    131      * @param value a value to wrap
    132      * @return a pooled supplier of {@code value}
    133      */
    134     static PooledSupplier.OfInt obtainSupplier(int value) {
    135         PooledLambdaImpl r = acquireConstSupplier(ReturnType.INT);
    136         r.mConstValue = value;
    137         return r;
    138     }
    139 
    140     /**
    141      * Wraps the given value into a {@link PooledSupplier}
    142      *
    143      * @param value a value to wrap
    144      * @return a pooled supplier of {@code value}
    145      */
    146     static PooledSupplier.OfLong obtainSupplier(long value) {
    147         PooledLambdaImpl r = acquireConstSupplier(ReturnType.LONG);
    148         r.mConstValue = value;
    149         return r;
    150     }
    151 
    152     /**
    153      * Wraps the given value into a {@link PooledSupplier}
    154      *
    155      * @param value a value to wrap
    156      * @return a pooled supplier of {@code value}
    157      */
    158     static PooledSupplier.OfDouble obtainSupplier(double value) {
    159         PooledLambdaImpl r = acquireConstSupplier(ReturnType.DOUBLE);
    160         r.mConstValue = Double.doubleToRawLongBits(value);
    161         return r;
    162     }
    163 
    164     /**
    165      * {@link PooledRunnable} factory
    166      *
    167      * @param function non-capturing lambda(typically an unbounded method reference)
    168      *                 to be invoked on call
    169      * @param arg1 parameter supplied to {@code function} on call
    170      * @return a {@link PooledRunnable}, equivalent to lambda:
    171      *         {@code () -> function(arg1) }
    172      */
    173     static <A> PooledRunnable obtainRunnable(
    174             Consumer<? super A> function,
    175             A arg1) {
    176         return acquire(PooledLambdaImpl.sPool,
    177                 function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null);
    178     }
    179 
    180     /**
    181      * {@link PooledSupplier} factory
    182      *
    183      * @param function non-capturing lambda(typically an unbounded method reference)
    184      *                 to be invoked on call
    185      * @param arg1 parameter supplied to {@code function} on call
    186      * @return a {@link PooledSupplier}, equivalent to lambda:
    187      *         {@code () -> function(arg1) }
    188      */
    189     static <A> PooledSupplier<Boolean> obtainSupplier(
    190             Predicate<? super A> function,
    191             A arg1) {
    192         return acquire(PooledLambdaImpl.sPool,
    193                 function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null);
    194     }
    195 
    196     /**
    197      * {@link PooledSupplier} factory
    198      *
    199      * @param function non-capturing lambda(typically an unbounded method reference)
    200      *                 to be invoked on call
    201      * @param arg1 parameter supplied to {@code function} on call
    202      * @return a {@link PooledSupplier}, equivalent to lambda:
    203      *         {@code () -> function(arg1) }
    204      */
    205     static <A, R> PooledSupplier<R> obtainSupplier(
    206             Function<? super A, ? extends R> function,
    207             A arg1) {
    208         return acquire(PooledLambdaImpl.sPool,
    209                 function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null);
    210     }
    211 
    212     /**
    213      * Factory of {@link Message}s that contain an
    214      * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
    215      * {@link Message#getCallback internal callback}.
    216      *
    217      * The callback is equivalent to one obtainable via
    218      * {@link #obtainRunnable(Consumer, Object)}
    219      *
    220      * Note that using this method with {@link android.os.Handler#handleMessage}
    221      * is more efficient than the alternative of {@link android.os.Handler#post}
    222      * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
    223      * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
    224      *
    225      * You may optionally set a {@link Message#what} for the message if you want to be
    226      * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
    227      * there's no need to do so
    228      *
    229      * @param function non-capturing lambda(typically an unbounded method reference)
    230      *                 to be invoked on call
    231      * @param arg1 parameter supplied to {@code function} on call
    232      * @return a {@link Message} invoking {@code function(arg1) } when handled
    233      */
    234     static <A> Message obtainMessage(
    235             Consumer<? super A> function,
    236             A arg1) {
    237         synchronized (Message.sPoolSync) {
    238             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
    239                     function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null);
    240             return Message.obtain().setCallback(callback.recycleOnUse());
    241         }
    242     }
    243 
    244     /**
    245      * {@link PooledRunnable} factory
    246      *
    247      * @param function non-capturing lambda(typically an unbounded method reference)
    248      *                 to be invoked on call
    249      * @param arg1 parameter supplied to {@code function} on call
    250      * @param arg2 parameter supplied to {@code function} on call
    251      * @return a {@link PooledRunnable}, equivalent to lambda:
    252      *         {@code () -> function(arg1, arg2) }
    253      */
    254     static <A, B> PooledRunnable obtainRunnable(
    255             BiConsumer<? super A, ? super B> function,
    256             A arg1, B arg2) {
    257         return acquire(PooledLambdaImpl.sPool,
    258                 function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null);
    259     }
    260 
    261     /**
    262      * {@link PooledSupplier} factory
    263      *
    264      * @param function non-capturing lambda(typically an unbounded method reference)
    265      *                 to be invoked on call
    266      * @param arg1 parameter supplied to {@code function} on call
    267      * @param arg2 parameter supplied to {@code function} on call
    268      * @return a {@link PooledSupplier}, equivalent to lambda:
    269      *         {@code () -> function(arg1, arg2) }
    270      */
    271     static <A, B> PooledSupplier<Boolean> obtainSupplier(
    272             BiPredicate<? super A, ? super B> function,
    273             A arg1, B arg2) {
    274         return acquire(PooledLambdaImpl.sPool,
    275                 function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null);
    276     }
    277 
    278     /**
    279      * {@link PooledSupplier} factory
    280      *
    281      * @param function non-capturing lambda(typically an unbounded method reference)
    282      *                 to be invoked on call
    283      * @param arg1 parameter supplied to {@code function} on call
    284      * @param arg2 parameter supplied to {@code function} on call
    285      * @return a {@link PooledSupplier}, equivalent to lambda:
    286      *         {@code () -> function(arg1, arg2) }
    287      */
    288     static <A, B, R> PooledSupplier<R> obtainSupplier(
    289             BiFunction<? super A, ? super B, ? extends R> function,
    290             A arg1, B arg2) {
    291         return acquire(PooledLambdaImpl.sPool,
    292                 function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null);
    293     }
    294 
    295     /**
    296      * {@link PooledConsumer} factory
    297      *
    298      * @param function non-capturing lambda(typically an unbounded method reference)
    299      *                 to be invoked on call
    300      * @param arg1 placeholder for a missing argument. Use {@link #__} to get one
    301      * @param arg2 parameter supplied to {@code function} on call
    302      * @return a {@link PooledConsumer}, equivalent to lambda:
    303      *         {@code (arg1) -> function(arg1, arg2) }
    304      */
    305     static <A, B> PooledConsumer<A> obtainConsumer(
    306             BiConsumer<? super A, ? super B> function,
    307             ArgumentPlaceholder<A> arg1, B arg2) {
    308         return acquire(PooledLambdaImpl.sPool,
    309                 function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null);
    310     }
    311 
    312     /**
    313      * {@link PooledPredicate} factory
    314      *
    315      * @param function non-capturing lambda(typically an unbounded method reference)
    316      *                 to be invoked on call
    317      * @param arg1 placeholder for a missing argument. Use {@link #__} to get one
    318      * @param arg2 parameter supplied to {@code function} on call
    319      * @return a {@link PooledPredicate}, equivalent to lambda:
    320      *         {@code (arg1) -> function(arg1, arg2) }
    321      */
    322     static <A, B> PooledPredicate<A> obtainPredicate(
    323             BiPredicate<? super A, ? super B> function,
    324             ArgumentPlaceholder<A> arg1, B arg2) {
    325         return acquire(PooledLambdaImpl.sPool,
    326                 function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null);
    327     }
    328 
    329     /**
    330      * {@link PooledFunction} factory
    331      *
    332      * @param function non-capturing lambda(typically an unbounded method reference)
    333      *                 to be invoked on call
    334      * @param arg1 placeholder for a missing argument. Use {@link #__} to get one
    335      * @param arg2 parameter supplied to {@code function} on call
    336      * @return a {@link PooledFunction}, equivalent to lambda:
    337      *         {@code (arg1) -> function(arg1, arg2) }
    338      */
    339     static <A, B, R> PooledFunction<A, R> obtainFunction(
    340             BiFunction<? super A, ? super B, ? extends R> function,
    341             ArgumentPlaceholder<A> arg1, B arg2) {
    342         return acquire(PooledLambdaImpl.sPool,
    343                 function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null);
    344     }
    345 
    346     /**
    347      * {@link PooledConsumer} factory
    348      *
    349      * @param function non-capturing lambda(typically an unbounded method reference)
    350      *                 to be invoked on call
    351      * @param arg1 parameter supplied to {@code function} on call
    352      * @param arg2 placeholder for a missing argument. Use {@link #__} to get one
    353      * @return a {@link PooledConsumer}, equivalent to lambda:
    354      *         {@code (arg2) -> function(arg1, arg2) }
    355      */
    356     static <A, B> PooledConsumer<B> obtainConsumer(
    357             BiConsumer<? super A, ? super B> function,
    358             A arg1, ArgumentPlaceholder<B> arg2) {
    359         return acquire(PooledLambdaImpl.sPool,
    360                 function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null);
    361     }
    362 
    363     /**
    364      * {@link PooledPredicate} factory
    365      *
    366      * @param function non-capturing lambda(typically an unbounded method reference)
    367      *                 to be invoked on call
    368      * @param arg1 parameter supplied to {@code function} on call
    369      * @param arg2 placeholder for a missing argument. Use {@link #__} to get one
    370      * @return a {@link PooledPredicate}, equivalent to lambda:
    371      *         {@code (arg2) -> function(arg1, arg2) }
    372      */
    373     static <A, B> PooledPredicate<B> obtainPredicate(
    374             BiPredicate<? super A, ? super B> function,
    375             A arg1, ArgumentPlaceholder<B> arg2) {
    376         return acquire(PooledLambdaImpl.sPool,
    377                 function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null);
    378     }
    379 
    380     /**
    381      * {@link PooledFunction} factory
    382      *
    383      * @param function non-capturing lambda(typically an unbounded method reference)
    384      *                 to be invoked on call
    385      * @param arg1 parameter supplied to {@code function} on call
    386      * @param arg2 placeholder for a missing argument. Use {@link #__} to get one
    387      * @return a {@link PooledFunction}, equivalent to lambda:
    388      *         {@code (arg2) -> function(arg1, arg2) }
    389      */
    390     static <A, B, R> PooledFunction<B, R> obtainFunction(
    391             BiFunction<? super A, ? super B, ? extends R> function,
    392             A arg1, ArgumentPlaceholder<B> arg2) {
    393         return acquire(PooledLambdaImpl.sPool,
    394                 function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null);
    395     }
    396 
    397     /**
    398      * Factory of {@link Message}s that contain an
    399      * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
    400      * {@link Message#getCallback internal callback}.
    401      *
    402      * The callback is equivalent to one obtainable via
    403      * {@link #obtainRunnable(BiConsumer, Object, Object)}
    404      *
    405      * Note that using this method with {@link android.os.Handler#handleMessage}
    406      * is more efficient than the alternative of {@link android.os.Handler#post}
    407      * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
    408      * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
    409      *
    410      * You may optionally set a {@link Message#what} for the message if you want to be
    411      * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
    412      * there's no need to do so
    413      *
    414      * @param function non-capturing lambda(typically an unbounded method reference)
    415      *                 to be invoked on call
    416      * @param arg1 parameter supplied to {@code function} on call
    417      * @param arg2 parameter supplied to {@code function} on call
    418      * @return a {@link Message} invoking {@code function(arg1, arg2) } when handled
    419      */
    420     static <A, B> Message obtainMessage(
    421             BiConsumer<? super A, ? super B> function,
    422             A arg1, B arg2) {
    423         synchronized (Message.sPoolSync) {
    424             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
    425                     function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null);
    426             return Message.obtain().setCallback(callback.recycleOnUse());
    427         }
    428     }
    429 
    430     /**
    431      * {@link PooledRunnable} factory
    432      *
    433      * @param function non-capturing lambda(typically an unbounded method reference)
    434      *                 to be invoked on call
    435      * @param arg1 parameter supplied to {@code function} on call
    436      * @param arg2 parameter supplied to {@code function} on call
    437      * @param arg3 parameter supplied to {@code function} on call
    438      * @return a {@link PooledRunnable}, equivalent to lambda:
    439      *         {@code () -> function(arg1, arg2, arg3) }
    440      */
    441     static <A, B, C> PooledRunnable obtainRunnable(
    442             TriConsumer<? super A, ? super B, ? super C> function,
    443             A arg1, B arg2, C arg3) {
    444         return acquire(PooledLambdaImpl.sPool,
    445                 function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
    446     }
    447 
    448     /**
    449      * {@link PooledSupplier} factory
    450      *
    451      * @param function non-capturing lambda(typically an unbounded method reference)
    452      *                 to be invoked on call
    453      * @param arg1 parameter supplied to {@code function} on call
    454      * @param arg2 parameter supplied to {@code function} on call
    455      * @param arg3 parameter supplied to {@code function} on call
    456      * @return a {@link PooledSupplier}, equivalent to lambda:
    457      *         {@code () -> function(arg1, arg2, arg3) }
    458      */
    459     static <A, B, C, R> PooledSupplier<R> obtainSupplier(
    460             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
    461             A arg1, B arg2, C arg3) {
    462         return acquire(PooledLambdaImpl.sPool,
    463                 function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
    464     }
    465 
    466     /**
    467      * {@link PooledConsumer} factory
    468      *
    469      * @param function non-capturing lambda(typically an unbounded method reference)
    470      *                 to be invoked on call
    471      * @param arg1 placeholder for a missing argument. Use {@link #__} to get one
    472      * @param arg2 parameter supplied to {@code function} on call
    473      * @param arg3 parameter supplied to {@code function} on call
    474      * @return a {@link PooledConsumer}, equivalent to lambda:
    475      *         {@code (arg1) -> function(arg1, arg2, arg3) }
    476      */
    477     static <A, B, C> PooledConsumer<A> obtainConsumer(
    478             TriConsumer<? super A, ? super B, ? super C> function,
    479             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
    480         return acquire(PooledLambdaImpl.sPool,
    481                 function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
    482     }
    483 
    484     /**
    485      * {@link PooledFunction} factory
    486      *
    487      * @param function non-capturing lambda(typically an unbounded method reference)
    488      *                 to be invoked on call
    489      * @param arg1 placeholder for a missing argument. Use {@link #__} to get one
    490      * @param arg2 parameter supplied to {@code function} on call
    491      * @param arg3 parameter supplied to {@code function} on call
    492      * @return a {@link PooledFunction}, equivalent to lambda:
    493      *         {@code (arg1) -> function(arg1, arg2, arg3) }
    494      */
    495     static <A, B, C, R> PooledFunction<A, R> obtainFunction(
    496             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
    497             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
    498         return acquire(PooledLambdaImpl.sPool,
    499                 function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
    500     }
    501 
    502     /**
    503      * {@link PooledConsumer} factory
    504      *
    505      * @param function non-capturing lambda(typically an unbounded method reference)
    506      *                 to be invoked on call
    507      * @param arg1 parameter supplied to {@code function} on call
    508      * @param arg2 placeholder for a missing argument. Use {@link #__} to get one
    509      * @param arg3 parameter supplied to {@code function} on call
    510      * @return a {@link PooledConsumer}, equivalent to lambda:
    511      *         {@code (arg2) -> function(arg1, arg2, arg3) }
    512      */
    513     static <A, B, C> PooledConsumer<B> obtainConsumer(
    514             TriConsumer<? super A, ? super B, ? super C> function,
    515             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
    516         return acquire(PooledLambdaImpl.sPool,
    517                 function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
    518     }
    519 
    520     /**
    521      * {@link PooledFunction} factory
    522      *
    523      * @param function non-capturing lambda(typically an unbounded method reference)
    524      *                 to be invoked on call
    525      * @param arg1 parameter supplied to {@code function} on call
    526      * @param arg2 placeholder for a missing argument. Use {@link #__} to get one
    527      * @param arg3 parameter supplied to {@code function} on call
    528      * @return a {@link PooledFunction}, equivalent to lambda:
    529      *         {@code (arg2) -> function(arg1, arg2, arg3) }
    530      */
    531     static <A, B, C, R> PooledFunction<B, R> obtainFunction(
    532             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
    533             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
    534         return acquire(PooledLambdaImpl.sPool,
    535                 function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
    536     }
    537 
    538     /**
    539      * {@link PooledConsumer} factory
    540      *
    541      * @param function non-capturing lambda(typically an unbounded method reference)
    542      *                 to be invoked on call
    543      * @param arg1 parameter supplied to {@code function} on call
    544      * @param arg2 parameter supplied to {@code function} on call
    545      * @param arg3 placeholder for a missing argument. Use {@link #__} to get one
    546      * @return a {@link PooledConsumer}, equivalent to lambda:
    547      *         {@code (arg3) -> function(arg1, arg2, arg3) }
    548      */
    549     static <A, B, C> PooledConsumer<C> obtainConsumer(
    550             TriConsumer<? super A, ? super B, ? super C> function,
    551             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
    552         return acquire(PooledLambdaImpl.sPool,
    553                 function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
    554     }
    555 
    556     /**
    557      * {@link PooledFunction} factory
    558      *
    559      * @param function non-capturing lambda(typically an unbounded method reference)
    560      *                 to be invoked on call
    561      * @param arg1 parameter supplied to {@code function} on call
    562      * @param arg2 parameter supplied to {@code function} on call
    563      * @param arg3 placeholder for a missing argument. Use {@link #__} to get one
    564      * @return a {@link PooledFunction}, equivalent to lambda:
    565      *         {@code (arg3) -> function(arg1, arg2, arg3) }
    566      */
    567     static <A, B, C, R> PooledFunction<C, R> obtainFunction(
    568             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
    569             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
    570         return acquire(PooledLambdaImpl.sPool,
    571                 function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
    572     }
    573 
    574     /**
    575      * Factory of {@link Message}s that contain an
    576      * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
    577      * {@link Message#getCallback internal callback}.
    578      *
    579      * The callback is equivalent to one obtainable via
    580      * {@link #obtainRunnable(TriConsumer, Object, Object, Object)}
    581      *
    582      * Note that using this method with {@link android.os.Handler#handleMessage}
    583      * is more efficient than the alternative of {@link android.os.Handler#post}
    584      * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
    585      * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
    586      *
    587      * You may optionally set a {@link Message#what} for the message if you want to be
    588      * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
    589      * there's no need to do so
    590      *
    591      * @param function non-capturing lambda(typically an unbounded method reference)
    592      *                 to be invoked on call
    593      * @param arg1 parameter supplied to {@code function} on call
    594      * @param arg2 parameter supplied to {@code function} on call
    595      * @param arg3 parameter supplied to {@code function} on call
    596      * @return a {@link Message} invoking {@code function(arg1, arg2, arg3) } when handled
    597      */
    598     static <A, B, C> Message obtainMessage(
    599             TriConsumer<? super A, ? super B, ? super C> function,
    600             A arg1, B arg2, C arg3) {
    601         synchronized (Message.sPoolSync) {
    602             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
    603                     function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
    604             return Message.obtain().setCallback(callback.recycleOnUse());
    605         }
    606     }
    607 
    608     /**
    609      * {@link PooledRunnable} factory
    610      *
    611      * @param function non-capturing lambda(typically an unbounded method reference)
    612      *                 to be invoked on call
    613      * @param arg1 parameter supplied to {@code function} on call
    614      * @param arg2 parameter supplied to {@code function} on call
    615      * @param arg3 parameter supplied to {@code function} on call
    616      * @param arg4 parameter supplied to {@code function} on call
    617      * @return a {@link PooledRunnable}, equivalent to lambda:
    618      *         {@code () -> function(arg1, arg2, arg3, arg4) }
    619      */
    620     static <A, B, C, D> PooledRunnable obtainRunnable(
    621             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
    622             A arg1, B arg2, C arg3, D arg4) {
    623         return acquire(PooledLambdaImpl.sPool,
    624                 function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
    625     }
    626 
    627     /**
    628      * {@link PooledSupplier} factory
    629      *
    630      * @param function non-capturing lambda(typically an unbounded method reference)
    631      *                 to be invoked on call
    632      * @param arg1 parameter supplied to {@code function} on call
    633      * @param arg2 parameter supplied to {@code function} on call
    634      * @param arg3 parameter supplied to {@code function} on call
    635      * @param arg4 parameter supplied to {@code function} on call
    636      * @return a {@link PooledSupplier}, equivalent to lambda:
    637      *         {@code () -> function(arg1, arg2, arg3, arg4) }
    638      */
    639     static <A, B, C, D, R> PooledSupplier<R> obtainSupplier(
    640             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
    641             A arg1, B arg2, C arg3, D arg4) {
    642         return acquire(PooledLambdaImpl.sPool,
    643                 function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
    644     }
    645 
    646     /**
    647      * {@link PooledConsumer} factory
    648      *
    649      * @param function non-capturing lambda(typically an unbounded method reference)
    650      *                 to be invoked on call
    651      * @param arg1 placeholder for a missing argument. Use {@link #__} to get one
    652      * @param arg2 parameter supplied to {@code function} on call
    653      * @param arg3 parameter supplied to {@code function} on call
    654      * @param arg4 parameter supplied to {@code function} on call
    655      * @return a {@link PooledConsumer}, equivalent to lambda:
    656      *         {@code (arg1) -> function(arg1, arg2, arg3, arg4) }
    657      */
    658     static <A, B, C, D> PooledConsumer<A> obtainConsumer(
    659             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
    660             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
    661         return acquire(PooledLambdaImpl.sPool,
    662                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
    663     }
    664 
    665     /**
    666      * {@link PooledFunction} factory
    667      *
    668      * @param function non-capturing lambda(typically an unbounded method reference)
    669      *                 to be invoked on call
    670      * @param arg1 placeholder for a missing argument. Use {@link #__} to get one
    671      * @param arg2 parameter supplied to {@code function} on call
    672      * @param arg3 parameter supplied to {@code function} on call
    673      * @param arg4 parameter supplied to {@code function} on call
    674      * @return a {@link PooledFunction}, equivalent to lambda:
    675      *         {@code (arg1) -> function(arg1, arg2, arg3, arg4) }
    676      */
    677     static <A, B, C, D, R> PooledFunction<A, R> obtainFunction(
    678             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
    679             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
    680         return acquire(PooledLambdaImpl.sPool,
    681                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
    682     }
    683 
    684     /**
    685      * {@link PooledConsumer} factory
    686      *
    687      * @param function non-capturing lambda(typically an unbounded method reference)
    688      *                 to be invoked on call
    689      * @param arg1 parameter supplied to {@code function} on call
    690      * @param arg2 placeholder for a missing argument. Use {@link #__} to get one
    691      * @param arg3 parameter supplied to {@code function} on call
    692      * @param arg4 parameter supplied to {@code function} on call
    693      * @return a {@link PooledConsumer}, equivalent to lambda:
    694      *         {@code (arg2) -> function(arg1, arg2, arg3, arg4) }
    695      */
    696     static <A, B, C, D> PooledConsumer<B> obtainConsumer(
    697             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
    698             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
    699         return acquire(PooledLambdaImpl.sPool,
    700                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
    701     }
    702 
    703     /**
    704      * {@link PooledFunction} factory
    705      *
    706      * @param function non-capturing lambda(typically an unbounded method reference)
    707      *                 to be invoked on call
    708      * @param arg1 parameter supplied to {@code function} on call
    709      * @param arg2 placeholder for a missing argument. Use {@link #__} to get one
    710      * @param arg3 parameter supplied to {@code function} on call
    711      * @param arg4 parameter supplied to {@code function} on call
    712      * @return a {@link PooledFunction}, equivalent to lambda:
    713      *         {@code (arg2) -> function(arg1, arg2, arg3, arg4) }
    714      */
    715     static <A, B, C, D, R> PooledFunction<B, R> obtainFunction(
    716             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
    717             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
    718         return acquire(PooledLambdaImpl.sPool,
    719                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
    720     }
    721 
    722     /**
    723      * {@link PooledConsumer} factory
    724      *
    725      * @param function non-capturing lambda(typically an unbounded method reference)
    726      *                 to be invoked on call
    727      * @param arg1 parameter supplied to {@code function} on call
    728      * @param arg2 parameter supplied to {@code function} on call
    729      * @param arg3 placeholder for a missing argument. Use {@link #__} to get one
    730      * @param arg4 parameter supplied to {@code function} on call
    731      * @return a {@link PooledConsumer}, equivalent to lambda:
    732      *         {@code (arg3) -> function(arg1, arg2, arg3, arg4) }
    733      */
    734     static <A, B, C, D> PooledConsumer<C> obtainConsumer(
    735             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
    736             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
    737         return acquire(PooledLambdaImpl.sPool,
    738                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
    739     }
    740 
    741     /**
    742      * {@link PooledFunction} factory
    743      *
    744      * @param function non-capturing lambda(typically an unbounded method reference)
    745      *                 to be invoked on call
    746      * @param arg1 parameter supplied to {@code function} on call
    747      * @param arg2 parameter supplied to {@code function} on call
    748      * @param arg3 placeholder for a missing argument. Use {@link #__} to get one
    749      * @param arg4 parameter supplied to {@code function} on call
    750      * @return a {@link PooledFunction}, equivalent to lambda:
    751      *         {@code (arg3) -> function(arg1, arg2, arg3, arg4) }
    752      */
    753     static <A, B, C, D, R> PooledFunction<C, R> obtainFunction(
    754             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
    755             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
    756         return acquire(PooledLambdaImpl.sPool,
    757                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
    758     }
    759 
    760     /**
    761      * {@link PooledConsumer} factory
    762      *
    763      * @param function non-capturing lambda(typically an unbounded method reference)
    764      *                 to be invoked on call
    765      * @param arg1 parameter supplied to {@code function} on call
    766      * @param arg2 parameter supplied to {@code function} on call
    767      * @param arg3 parameter supplied to {@code function} on call
    768      * @param arg4 placeholder for a missing argument. Use {@link #__} to get one
    769      * @return a {@link PooledConsumer}, equivalent to lambda:
    770      *         {@code (arg4) -> function(arg1, arg2, arg3, arg4) }
    771      */
    772     static <A, B, C, D> PooledConsumer<D> obtainConsumer(
    773             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
    774             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
    775         return acquire(PooledLambdaImpl.sPool,
    776                 function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
    777     }
    778 
    779     /**
    780      * {@link PooledFunction} factory
    781      *
    782      * @param function non-capturing lambda(typically an unbounded method reference)
    783      *                 to be invoked on call
    784      * @param arg1 parameter supplied to {@code function} on call
    785      * @param arg2 parameter supplied to {@code function} on call
    786      * @param arg3 parameter supplied to {@code function} on call
    787      * @param arg4 placeholder for a missing argument. Use {@link #__} to get one
    788      * @return a {@link PooledFunction}, equivalent to lambda:
    789      *         {@code (arg4) -> function(arg1, arg2, arg3, arg4) }
    790      */
    791     static <A, B, C, D, R> PooledFunction<D, R> obtainFunction(
    792             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
    793             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
    794         return acquire(PooledLambdaImpl.sPool,
    795                 function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
    796     }
    797 
    798     /**
    799      * Factory of {@link Message}s that contain an
    800      * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
    801      * {@link Message#getCallback internal callback}.
    802      *
    803      * The callback is equivalent to one obtainable via
    804      * {@link #obtainRunnable(QuadConsumer, Object, Object, Object, Object)}
    805      *
    806      * Note that using this method with {@link android.os.Handler#handleMessage}
    807      * is more efficient than the alternative of {@link android.os.Handler#post}
    808      * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
    809      * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
    810      *
    811      * You may optionally set a {@link Message#what} for the message if you want to be
    812      * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
    813      * there's no need to do so
    814      *
    815      * @param function non-capturing lambda(typically an unbounded method reference)
    816      *                 to be invoked on call
    817      * @param arg1 parameter supplied to {@code function} on call
    818      * @param arg2 parameter supplied to {@code function} on call
    819      * @param arg3 parameter supplied to {@code function} on call
    820      * @param arg4 parameter supplied to {@code function} on call
    821      * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4) } when handled
    822      */
    823     static <A, B, C, D> Message obtainMessage(
    824             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
    825             A arg1, B arg2, C arg3, D arg4) {
    826         synchronized (Message.sPoolSync) {
    827             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
    828                     function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
    829             return Message.obtain().setCallback(callback.recycleOnUse());
    830         }
    831     }
    832 
    833     /**
    834      * {@link PooledRunnable} factory
    835      *
    836      * @param function non-capturing lambda(typically an unbounded method reference)
    837      *                 to be invoked on call
    838      * @param arg1 parameter supplied to {@code function} on call
    839      * @param arg2 parameter supplied to {@code function} on call
    840      * @param arg3 parameter supplied to {@code function} on call
    841      * @param arg4 parameter supplied to {@code function} on call
    842      * @param arg5 parameter supplied to {@code function} on call
    843      * @return a {@link PooledRunnable}, equivalent to lambda:
    844      *         {@code () -> function(arg1, arg2, arg3, arg4, arg5) }
    845      */
    846     static <A, B, C, D, E> PooledRunnable obtainRunnable(
    847             QuintConsumer<? super A, ? super B, ? super C, ? super D, ? super E> function,
    848             A arg1, B arg2, C arg3, D arg4, E arg5) {
    849         return acquire(PooledLambdaImpl.sPool,
    850                 function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null);
    851     }
    852 
    853     /**
    854      * {@link PooledSupplier} factory
    855      *
    856      * @param function non-capturing lambda(typically an unbounded method reference)
    857      *                 to be invoked on call
    858      * @param arg1 parameter supplied to {@code function} on call
    859      * @param arg2 parameter supplied to {@code function} on call
    860      * @param arg3 parameter supplied to {@code function} on call
    861      * @param arg4 parameter supplied to {@code function} on call
    862      * @param arg5 parameter supplied to {@code function} on call
    863      * @return a {@link PooledSupplier}, equivalent to lambda:
    864      *         {@code () -> function(arg1, arg2, arg3, arg4, arg5) }
    865      */
    866     static <A, B, C, D, E, R> PooledSupplier<R> obtainSupplier(
    867             QuintFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? extends R>
    868                     function, A arg1, B arg2, C arg3, D arg4, E arg5) {
    869         return acquire(PooledLambdaImpl.sPool,
    870                 function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null);
    871     }
    872 
    873     /**
    874      * Factory of {@link Message}s that contain an
    875      * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
    876      * {@link Message#getCallback internal callback}.
    877      *
    878      * The callback is equivalent to one obtainable via
    879      * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
    880      *
    881      * Note that using this method with {@link android.os.Handler#handleMessage}
    882      * is more efficient than the alternative of {@link android.os.Handler#post}
    883      * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
    884      * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
    885      *
    886      * You may optionally set a {@link Message#what} for the message if you want to be
    887      * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
    888      * there's no need to do so
    889      *
    890      * @param function non-capturing lambda(typically an unbounded method reference)
    891      *                 to be invoked on call
    892      * @param arg1 parameter supplied to {@code function} on call
    893      * @param arg2 parameter supplied to {@code function} on call
    894      * @param arg3 parameter supplied to {@code function} on call
    895      * @param arg4 parameter supplied to {@code function} on call
    896      * @param arg5 parameter supplied to {@code function} on call
    897      * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5) } when
    898      *         handled
    899      */
    900     static <A, B, C, D, E> Message obtainMessage(
    901             QuintConsumer<? super A, ? super B, ? super C, ? super D, ? super E> function,
    902             A arg1, B arg2, C arg3, D arg4, E arg5) {
    903         synchronized (Message.sPoolSync) {
    904             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
    905                     function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null);
    906             return Message.obtain().setCallback(callback.recycleOnUse());
    907         }
    908     }
    909 
    910     /**
    911      * {@link PooledRunnable} factory
    912      *
    913      * @param function non-capturing lambda(typically an unbounded method reference)
    914      *                 to be invoked on call
    915      * @param arg1 parameter supplied to {@code function} on call
    916      * @param arg2 parameter supplied to {@code function} on call
    917      * @param arg3 parameter supplied to {@code function} on call
    918      * @param arg4 parameter supplied to {@code function} on call
    919      * @param arg5 parameter supplied to {@code function} on call
    920      * @param arg6 parameter supplied to {@code function} on call
    921      * @return a {@link PooledRunnable}, equivalent to lambda:
    922      *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6) }
    923      */
    924     static <A, B, C, D, E, F> PooledRunnable obtainRunnable(
    925             HexConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F> function,
    926             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
    927         return acquire(PooledLambdaImpl.sPool,
    928                 function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6);
    929     }
    930 
    931     /**
    932      * {@link PooledSupplier} factory
    933      *
    934      * @param function non-capturing lambda(typically an unbounded method reference)
    935      *                 to be invoked on call
    936      * @param arg1 parameter supplied to {@code function} on call
    937      * @param arg2 parameter supplied to {@code function} on call
    938      * @param arg3 parameter supplied to {@code function} on call
    939      * @param arg4 parameter supplied to {@code function} on call
    940      * @param arg5 parameter supplied to {@code function} on call
    941      * @param arg6 parameter supplied to {@code function} on call
    942      * @return a {@link PooledSupplier}, equivalent to lambda:
    943      *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6) }
    944      */
    945     static <A, B, C, D, E, F, R> PooledSupplier<R> obtainSupplier(
    946             HexFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
    947                     ? extends R> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
    948         return acquire(PooledLambdaImpl.sPool,
    949                 function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6);
    950     }
    951 
    952     /**
    953      * Factory of {@link Message}s that contain an
    954      * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
    955      * {@link Message#getCallback internal callback}.
    956      *
    957      * The callback is equivalent to one obtainable via
    958      * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
    959      *
    960      * Note that using this method with {@link android.os.Handler#handleMessage}
    961      * is more efficient than the alternative of {@link android.os.Handler#post}
    962      * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
    963      * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
    964      *
    965      * You may optionally set a {@link Message#what} for the message if you want to be
    966      * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
    967      * there's no need to do so
    968      *
    969      * @param function non-capturing lambda(typically an unbounded method reference)
    970      *                 to be invoked on call
    971      * @param arg1 parameter supplied to {@code function} on call
    972      * @param arg2 parameter supplied to {@code function} on call
    973      * @param arg3 parameter supplied to {@code function} on call
    974      * @param arg4 parameter supplied to {@code function} on call
    975      * @param arg5 parameter supplied to {@code function} on call
    976      * @param arg6 parameter supplied to {@code function} on call
    977      * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6) }
    978      *         when handled
    979      */
    980     static <A, B, C, D, E, F> Message obtainMessage(
    981             HexConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F> function,
    982             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
    983         synchronized (Message.sPoolSync) {
    984             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
    985                     function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6);
    986             return Message.obtain().setCallback(callback.recycleOnUse());
    987         }
    988     }
    989 }
    990