• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.annotation.Nullable;
20 import android.os.Message;
21 import android.text.TextUtils;
22 import android.util.Log;
23 import android.util.Pools;
24 
25 import com.android.internal.util.ArrayUtils;
26 import com.android.internal.util.BitUtils;
27 import com.android.internal.util.FunctionalUtils;
28 import com.android.internal.util.function.DecConsumer;
29 import com.android.internal.util.function.DecFunction;
30 import com.android.internal.util.function.DecPredicate;
31 import com.android.internal.util.function.DodecConsumer;
32 import com.android.internal.util.function.DodecFunction;
33 import com.android.internal.util.function.DodecPredicate;
34 import com.android.internal.util.function.HeptConsumer;
35 import com.android.internal.util.function.HeptFunction;
36 import com.android.internal.util.function.HeptPredicate;
37 import com.android.internal.util.function.HexConsumer;
38 import com.android.internal.util.function.HexFunction;
39 import com.android.internal.util.function.HexPredicate;
40 import com.android.internal.util.function.NonaConsumer;
41 import com.android.internal.util.function.NonaFunction;
42 import com.android.internal.util.function.NonaPredicate;
43 import com.android.internal.util.function.OctConsumer;
44 import com.android.internal.util.function.OctFunction;
45 import com.android.internal.util.function.OctPredicate;
46 import com.android.internal.util.function.QuadConsumer;
47 import com.android.internal.util.function.QuadFunction;
48 import com.android.internal.util.function.QuadPredicate;
49 import com.android.internal.util.function.QuintConsumer;
50 import com.android.internal.util.function.QuintFunction;
51 import com.android.internal.util.function.QuintPredicate;
52 import com.android.internal.util.function.TriConsumer;
53 import com.android.internal.util.function.TriFunction;
54 import com.android.internal.util.function.TriPredicate;
55 import com.android.internal.util.function.UndecConsumer;
56 import com.android.internal.util.function.UndecFunction;
57 import com.android.internal.util.function.UndecPredicate;
58 
59 import java.util.Arrays;
60 import java.util.Objects;
61 import java.util.function.BiConsumer;
62 import java.util.function.BiFunction;
63 import java.util.function.BiPredicate;
64 import java.util.function.Consumer;
65 import java.util.function.Function;
66 import java.util.function.Predicate;
67 import java.util.function.Supplier;
68 
69 /**
70  * @see PooledLambda
71  * @hide
72  */
73 final class PooledLambdaImpl<R> extends OmniFunction<Object,
74         Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, R> {
75 
76     private static final boolean DEBUG = false;
77     private static final String LOG_TAG = "PooledLambdaImpl";
78 
79     private static final int MAX_ARGS = 11;
80 
81     private static final int MAX_POOL_SIZE = 50;
82 
83     static class Pool extends Pools.SynchronizedPool<PooledLambdaImpl> {
84 
Pool(Object lock)85         public Pool(Object lock) {
86             super(MAX_POOL_SIZE, lock);
87         }
88     }
89 
90     static final Pool sPool = new Pool(new Object());
91     static final Pool sMessageCallbacksPool = new Pool(Message.sPoolSync);
92 
PooledLambdaImpl()93     private PooledLambdaImpl() {}
94 
95     /**
96      * The function reference to be invoked
97      *
98      * May be the return value itself in case when an immediate result constant is provided instead
99      */
100     Object mFunc;
101 
102     /**
103      * A primitive result value to be immediately returned on invocation instead of calling
104      * {@link #mFunc}
105      */
106     long mConstValue;
107 
108     /**
109      * Arguments for {@link #mFunc}
110      */
111     @Nullable Object[] mArgs = null;
112 
113     /**
114      * Flag for {@link #mFlags}
115      *
116      * Indicates whether this instance is recycled
117      */
118     private static final int FLAG_RECYCLED = 1 << MAX_ARGS;
119 
120     /**
121      * Flag for {@link #mFlags}
122      *
123      * Indicates whether this instance should be immediately recycled on invocation
124      * (as requested via {@link PooledLambda#recycleOnUse()}) or not(default)
125      */
126     private static final int FLAG_RECYCLE_ON_USE = 1 << (MAX_ARGS + 1);
127 
128     /**
129      * Flag for {@link #mFlags}
130      *
131      * Indicates that this instance was acquired from {@link #sMessageCallbacksPool} as opposed to
132      * {@link #sPool}
133      */
134     private static final int FLAG_ACQUIRED_FROM_MESSAGE_CALLBACKS_POOL = 1 << (MAX_ARGS + 2);
135 
136     /** @see #mFlags */
137     static final int MASK_EXPOSED_AS = LambdaType.MASK << (MAX_ARGS + 3);
138 
139     /** @see #mFlags */
140     static final int MASK_FUNC_TYPE = LambdaType.MASK <<
141             (MAX_ARGS + 3 + LambdaType.MASK_BIT_COUNT);
142 
143     /**
144      * Bit schema:
145      * AAAAAAAAAAABCDEEEEEEFFFFFF
146      *
147      * Where:
148      * A - whether {@link #mArgs arg} at corresponding index was specified at
149      * {@link #acquire creation time} (0) or {@link #invoke invocation time} (1)
150      * B - {@link #FLAG_RECYCLED}
151      * C - {@link #FLAG_RECYCLE_ON_USE}
152      * D - {@link #FLAG_ACQUIRED_FROM_MESSAGE_CALLBACKS_POOL}
153      * E - {@link LambdaType} representing the type of the lambda returned to the caller from a
154      * factory method
155      * F - {@link LambdaType} of {@link #mFunc} as resolved when calling a factory method
156      */
157     int mFlags = 0;
158 
159 
160     @Override
recycle()161     public void recycle() {
162         if (DEBUG) Log.i(LOG_TAG, this + ".recycle()");
163         if (!isRecycled()) doRecycle();
164     }
165 
doRecycle()166     private void doRecycle() {
167         if (DEBUG) Log.i(LOG_TAG, this + ".doRecycle()");
168         Pool pool = (mFlags & FLAG_ACQUIRED_FROM_MESSAGE_CALLBACKS_POOL) != 0
169                 ? PooledLambdaImpl.sMessageCallbacksPool
170                 : PooledLambdaImpl.sPool;
171 
172         mFunc = null;
173         if (mArgs != null) Arrays.fill(mArgs, null);
174         mFlags = FLAG_RECYCLED;
175         mConstValue = 0L;
176 
177         pool.release(this);
178     }
179 
180     @Override
invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9, Object a10, Object a11)181     R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7,
182             Object a8, Object a9, Object a10, Object a11) {
183         checkNotRecycled();
184         if (DEBUG) {
185             Log.i(LOG_TAG, this + ".invoke("
186                     + commaSeparateFirstN(
187                             new Object[] { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 },
188                             LambdaType.decodeArgCount(getFlags(MASK_EXPOSED_AS)))
189                     + ")");
190         }
191         final boolean notUsed = fillInArg(a1) && fillInArg(a2) && fillInArg(a3) && fillInArg(a4)
192                 && fillInArg(a5) && fillInArg(a6) && fillInArg(a7) && fillInArg(a8)
193                 && fillInArg(a9) && fillInArg(a10) && fillInArg(a11);
194         int argCount = LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE));
195         if (argCount != LambdaType.MASK_ARG_COUNT) {
196             for (int i = 0; i < argCount; i++) {
197                 if (mArgs[i] == ArgumentPlaceholder.INSTANCE) {
198                     throw new IllegalStateException("Missing argument #" + i + " among "
199                             + Arrays.toString(mArgs));
200                 }
201             }
202         }
203         try {
204             return doInvoke();
205         } finally {
206             if (isRecycleOnUse()) {
207                 doRecycle();
208             } else if (!isRecycled()) {
209                 int argsSize = ArrayUtils.size(mArgs);
210                 for (int i = 0; i < argsSize; i++) {
211                     popArg(i);
212                 }
213             }
214         }
215     }
216 
fillInArg(Object invocationArg)217     private boolean fillInArg(Object invocationArg) {
218         int argsSize = ArrayUtils.size(mArgs);
219         for (int i = 0; i < argsSize; i++) {
220             if (mArgs[i] == ArgumentPlaceholder.INSTANCE) {
221                 mArgs[i] = invocationArg;
222                 mFlags |= BitUtils.bitAt(i);
223                 return true;
224             }
225         }
226         if (invocationArg != null && invocationArg != ArgumentPlaceholder.INSTANCE) {
227             throw new IllegalStateException("No more arguments expected for provided arg "
228                     + invocationArg + " among " + Arrays.toString(mArgs));
229         }
230         return false;
231     }
232 
checkNotRecycled()233     private void checkNotRecycled() {
234         if (isRecycled()) throw new IllegalStateException("Instance is recycled: " + this);
235     }
236 
237     @SuppressWarnings("unchecked")
doInvoke()238     private R doInvoke() {
239         final int funcType = getFlags(MASK_FUNC_TYPE);
240         final int argCount = LambdaType.decodeArgCount(funcType);
241         final int returnType = LambdaType.decodeReturnType(funcType);
242 
243         switch (argCount) {
244             case LambdaType.MASK_ARG_COUNT: {
245                 switch (returnType) {
246                     case LambdaType.ReturnType.INT: return (R) (Integer) getAsInt();
247                     case LambdaType.ReturnType.LONG: return (R) (Long) getAsLong();
248                     case LambdaType.ReturnType.DOUBLE: return (R) (Double) getAsDouble();
249                     default: return (R) mFunc;
250                 }
251             }
252             case 0: {
253                 switch (returnType) {
254                     case LambdaType.ReturnType.VOID: {
255                         ((Runnable) mFunc).run();
256                         return null;
257                     }
258                     case LambdaType.ReturnType.BOOLEAN:
259                     case LambdaType.ReturnType.OBJECT: {
260                         return (R) ((Supplier) mFunc).get();
261                     }
262                 }
263             } break;
264             case 1: {
265                 switch (returnType) {
266                     case LambdaType.ReturnType.VOID: {
267                         ((Consumer) mFunc).accept(popArg(0));
268                         return null;
269                     }
270                     case LambdaType.ReturnType.BOOLEAN: {
271                         return (R) (Object) ((Predicate) mFunc).test(popArg(0));
272                     }
273                     case LambdaType.ReturnType.OBJECT: {
274                         return (R) ((Function) mFunc).apply(popArg(0));
275                     }
276                 }
277             } break;
278             case 2: {
279                 switch (returnType) {
280                     case LambdaType.ReturnType.VOID: {
281                         ((BiConsumer) mFunc).accept(popArg(0), popArg(1));
282                         return null;
283                     }
284                     case LambdaType.ReturnType.BOOLEAN: {
285                         return (R) (Object) ((BiPredicate) mFunc).test(popArg(0), popArg(1));
286                     }
287                     case LambdaType.ReturnType.OBJECT: {
288                         return (R) ((BiFunction) mFunc).apply(popArg(0), popArg(1));
289                     }
290                 }
291             } break;
292             case 3: {
293                 switch (returnType) {
294                     case LambdaType.ReturnType.VOID: {
295                         ((TriConsumer) mFunc).accept(popArg(0), popArg(1), popArg(2));
296                         return null;
297                     }
298                     case LambdaType.ReturnType.BOOLEAN: {
299                         return (R) (Object) ((TriPredicate) mFunc).test(
300                                 popArg(0), popArg(1), popArg(2));
301                     }
302                     case LambdaType.ReturnType.OBJECT: {
303                         return (R) ((TriFunction) mFunc).apply(popArg(0), popArg(1), popArg(2));
304                     }
305                 }
306             } break;
307             case 4: {
308                 switch (returnType) {
309                     case LambdaType.ReturnType.VOID: {
310                         ((QuadConsumer) mFunc).accept(popArg(0), popArg(1), popArg(2), popArg(3));
311                         return null;
312                     }
313                     case LambdaType.ReturnType.BOOLEAN: {
314                         return (R) (Object) ((QuadPredicate) mFunc).test(
315                                 popArg(0), popArg(1), popArg(2), popArg(3));
316                     }
317                     case LambdaType.ReturnType.OBJECT: {
318                         return (R) ((QuadFunction) mFunc).apply(
319                                 popArg(0), popArg(1), popArg(2), popArg(3));
320                     }
321                 }
322             } break;
323 
324             case 5: {
325                 switch (returnType) {
326                     case LambdaType.ReturnType.VOID: {
327                         ((QuintConsumer) mFunc).accept(popArg(0), popArg(1),
328                                 popArg(2), popArg(3), popArg(4));
329                         return null;
330                     }
331                     case LambdaType.ReturnType.BOOLEAN: {
332                         return (R) (Object) ((QuintPredicate) mFunc).test(
333                                 popArg(0), popArg(1), popArg(2), popArg(3), popArg(4));
334                     }
335                     case LambdaType.ReturnType.OBJECT: {
336                         return (R) ((QuintFunction) mFunc).apply(
337                                 popArg(0), popArg(1), popArg(2), popArg(3),  popArg(4));
338                     }
339                 }
340             } break;
341 
342             case 6: {
343                 switch (returnType) {
344                     case LambdaType.ReturnType.VOID: {
345                         ((HexConsumer) mFunc).accept(popArg(0), popArg(1),
346                                 popArg(2), popArg(3), popArg(4), popArg(5));
347                         return null;
348                     }
349                     case LambdaType.ReturnType.BOOLEAN: {
350                         return (R) (Object) ((HexPredicate) mFunc).test(popArg(0),
351                                 popArg(1), popArg(2), popArg(3), popArg(4), popArg(5));
352                     }
353                     case LambdaType.ReturnType.OBJECT: {
354                         return (R) ((HexFunction) mFunc).apply(popArg(0), popArg(1),
355                                 popArg(2), popArg(3), popArg(4), popArg(5));
356                     }
357                 }
358             } break;
359 
360             case 7: {
361                 switch (returnType) {
362                     case LambdaType.ReturnType.VOID: {
363                         ((HeptConsumer) mFunc).accept(popArg(0), popArg(1),
364                                 popArg(2), popArg(3), popArg(4),
365                                 popArg(5), popArg(6));
366                         return null;
367                     }
368                     case LambdaType.ReturnType.BOOLEAN: {
369                         return (R) (Object) ((HeptPredicate) mFunc).test(popArg(0),
370                                 popArg(1), popArg(2), popArg(3),
371                                 popArg(4), popArg(5), popArg(6));
372                     }
373                     case LambdaType.ReturnType.OBJECT: {
374                         return (R) ((HeptFunction) mFunc).apply(popArg(0), popArg(1),
375                                 popArg(2), popArg(3), popArg(4),
376                                 popArg(5), popArg(6));
377                     }
378                 }
379             } break;
380 
381             case 8: {
382                 switch (returnType) {
383                     case LambdaType.ReturnType.VOID: {
384                         ((OctConsumer) mFunc).accept(popArg(0), popArg(1),
385                                 popArg(2), popArg(3), popArg(4),
386                                 popArg(5), popArg(6), popArg(7));
387                         return null;
388                     }
389                     case LambdaType.ReturnType.BOOLEAN: {
390                         return (R) (Object) ((OctPredicate) mFunc).test(popArg(0),
391                                 popArg(1), popArg(2), popArg(3),
392                                 popArg(4), popArg(5), popArg(6), popArg(7));
393                     }
394                     case LambdaType.ReturnType.OBJECT: {
395                         return (R) ((OctFunction) mFunc).apply(popArg(0), popArg(1),
396                                 popArg(2), popArg(3), popArg(4),
397                                 popArg(5), popArg(6), popArg(7));
398                     }
399                 }
400             } break;
401 
402             case 9: {
403                 switch (returnType) {
404                     case LambdaType.ReturnType.VOID: {
405                         ((NonaConsumer) mFunc).accept(popArg(0), popArg(1),
406                                 popArg(2), popArg(3), popArg(4), popArg(5),
407                                 popArg(6), popArg(7), popArg(8));
408                         return null;
409                     }
410                     case LambdaType.ReturnType.BOOLEAN: {
411                         return (R) (Object) ((NonaPredicate) mFunc).test(popArg(0),
412                                 popArg(1), popArg(2), popArg(3), popArg(4),
413                                 popArg(5), popArg(6), popArg(7), popArg(8));
414                     }
415                     case LambdaType.ReturnType.OBJECT: {
416                         return (R) ((NonaFunction) mFunc).apply(popArg(0), popArg(1),
417                                 popArg(2), popArg(3), popArg(4), popArg(5),
418                                 popArg(6), popArg(7), popArg(8));
419                     }
420                 }
421             } break;
422 
423             case 10: {
424                 switch (returnType) {
425                     case LambdaType.ReturnType.VOID: {
426                         ((DecConsumer) mFunc).accept(popArg(0), popArg(1),
427                                 popArg(2), popArg(3), popArg(4), popArg(5),
428                                 popArg(6), popArg(7), popArg(8), popArg(9));
429                         return null;
430                     }
431                     case LambdaType.ReturnType.BOOLEAN: {
432                         return (R) (Object) ((DecPredicate) mFunc).test(popArg(0),
433                                 popArg(1), popArg(2), popArg(3), popArg(4),
434                                 popArg(5), popArg(6), popArg(7), popArg(8), popArg(9));
435                     }
436                     case LambdaType.ReturnType.OBJECT: {
437                         return (R) ((DecFunction) mFunc).apply(popArg(0), popArg(1),
438                                 popArg(2), popArg(3), popArg(4), popArg(5),
439                                 popArg(6), popArg(7), popArg(8), popArg(9));
440                     }
441                 }
442             } break;
443 
444             case 11: {
445                 switch (returnType) {
446                     case LambdaType.ReturnType.VOID: {
447                         ((UndecConsumer) mFunc).accept(popArg(0), popArg(1),
448                                 popArg(2), popArg(3), popArg(4), popArg(5),
449                                 popArg(6), popArg(7), popArg(8), popArg(9), popArg(10));
450                         return null;
451                     }
452                     case LambdaType.ReturnType.BOOLEAN: {
453                         return (R) (Object) ((UndecPredicate) mFunc).test(popArg(0),
454                                 popArg(1), popArg(2), popArg(3), popArg(4),
455                                 popArg(5), popArg(6), popArg(7), popArg(8), popArg(9), popArg(10));
456                     }
457                     case LambdaType.ReturnType.OBJECT: {
458                         return (R) ((UndecFunction) mFunc).apply(popArg(0), popArg(1),
459                                 popArg(2), popArg(3), popArg(4), popArg(5),
460                                 popArg(6), popArg(7), popArg(8), popArg(9), popArg(10));
461                     }
462                 }
463             } break;
464 
465             case 12: {
466                 switch (returnType) {
467                     case LambdaType.ReturnType.VOID: {
468                         ((DodecConsumer) mFunc).accept(popArg(0), popArg(1),
469                                 popArg(2), popArg(3), popArg(4), popArg(5),
470                                 popArg(6), popArg(7), popArg(8), popArg(9), popArg(10), popArg(11));
471                         return null;
472                     }
473                     case LambdaType.ReturnType.BOOLEAN: {
474                         return (R) (Object) ((DodecPredicate) mFunc).test(popArg(0),
475                                 popArg(1), popArg(2), popArg(3), popArg(4),
476                                 popArg(5), popArg(6), popArg(7), popArg(8), popArg(9), popArg(10),
477                                 popArg(11));
478                     }
479                     case LambdaType.ReturnType.OBJECT: {
480                         return (R) ((DodecFunction) mFunc).apply(popArg(0), popArg(1),
481                                 popArg(2), popArg(3), popArg(4), popArg(5),
482                                 popArg(6), popArg(7), popArg(8), popArg(9), popArg(10), popArg(11));
483                     }
484                 }
485             } break;
486         }
487         throw new IllegalStateException("Unknown function type: " + LambdaType.toString(funcType));
488     }
489 
isConstSupplier()490     private boolean isConstSupplier() {
491         return LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE)) == LambdaType.MASK_ARG_COUNT;
492     }
493 
popArg(int index)494     private Object popArg(int index) {
495         Object result = mArgs[index];
496         if (isInvocationArgAtIndex(index)) {
497             mArgs[index] = ArgumentPlaceholder.INSTANCE;
498             mFlags &= ~BitUtils.bitAt(index);
499         }
500         return result;
501     }
502 
503     @Override
toString()504     public String toString() {
505         if (isRecycled()) return "<recycled PooledLambda@" + hashCodeHex(this) + ">";
506 
507         StringBuilder sb = new StringBuilder();
508         if (isConstSupplier()) {
509             sb.append(getFuncTypeAsString()).append("(").append(doInvoke()).append(")");
510         } else {
511             Object func = mFunc;
512             if (func instanceof PooledLambdaImpl) {
513                 sb.append(func);
514             } else {
515                 sb.append(getFuncTypeAsString()).append("@").append(hashCodeHex(func));
516             }
517             sb.append("(");
518             sb.append(commaSeparateFirstN(mArgs,
519                     LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE))));
520             sb.append(")");
521         }
522         return sb.toString();
523     }
524 
commaSeparateFirstN(@ullable Object[] arr, int n)525     private String commaSeparateFirstN(@Nullable Object[] arr, int n) {
526         if (arr == null) return "";
527         return TextUtils.join(",", Arrays.copyOf(arr, n));
528     }
529 
hashCodeHex(Object o)530     private static String hashCodeHex(Object o) {
531         return Integer.toHexString(Objects.hashCode(o));
532     }
533 
getFuncTypeAsString()534     private String getFuncTypeAsString() {
535         if (isRecycled()) return "<recycled>";
536         if (isConstSupplier()) return "supplier";
537         String name = LambdaType.toString(getFlags(MASK_EXPOSED_AS));
538         if (name.endsWith("Consumer")) return "consumer";
539         if (name.endsWith("Function")) return "function";
540         if (name.endsWith("Predicate")) return "predicate";
541         if (name.endsWith("Supplier")) return "supplier";
542         if (name.endsWith("Runnable")) return "runnable";
543         return name;
544     }
545 
546     /**
547      * Internal non-typesafe factory method for {@link PooledLambdaImpl}
548      */
acquire(Pool pool, Object func, int fNumArgs, int numPlaceholders, int fReturnType, Object a, Object b, Object c, Object d, Object e, Object f, Object g, Object h, Object i, Object j, Object k, Object l)549     static <E extends PooledLambda> E acquire(Pool pool, Object func,
550             int fNumArgs, int numPlaceholders, int fReturnType, Object a, Object b, Object c,
551             Object d, Object e, Object f, Object g, Object h, Object i, Object j, Object k,
552             Object l) {
553         PooledLambdaImpl r = acquire(pool);
554         if (DEBUG) {
555             Log.i(LOG_TAG,
556                     "acquire(this = @" + hashCodeHex(r)
557                             + ", func = " + func
558                             + ", fNumArgs = " + fNumArgs
559                             + ", numPlaceholders = " + numPlaceholders
560                             + ", fReturnType = " + LambdaType.ReturnType.toString(fReturnType)
561                             + ", a = " + a
562                             + ", b = " + b
563                             + ", c = " + c
564                             + ", d = " + d
565                             + ", e = " + e
566                             + ", f = " + f
567                             + ", g = " + g
568                             + ", h = " + h
569                             + ", i = " + i
570                             + ", j = " + j
571                             + ", k = " + k
572                             + ", l = " + l
573                             + ")");
574         }
575         r.mFunc = Objects.requireNonNull(func);
576         r.setFlags(MASK_FUNC_TYPE, LambdaType.encode(fNumArgs, fReturnType));
577         r.setFlags(MASK_EXPOSED_AS, LambdaType.encode(numPlaceholders, fReturnType));
578         if (ArrayUtils.size(r.mArgs) < fNumArgs) r.mArgs = new Object[fNumArgs];
579         setIfInBounds(r.mArgs, 0, a);
580         setIfInBounds(r.mArgs, 1, b);
581         setIfInBounds(r.mArgs, 2, c);
582         setIfInBounds(r.mArgs, 3, d);
583         setIfInBounds(r.mArgs, 4, e);
584         setIfInBounds(r.mArgs, 5, f);
585         setIfInBounds(r.mArgs, 6, g);
586         setIfInBounds(r.mArgs, 7, h);
587         setIfInBounds(r.mArgs, 8, i);
588         setIfInBounds(r.mArgs, 9, j);
589         setIfInBounds(r.mArgs, 10, k);
590         setIfInBounds(r.mArgs, 11, l);
591         return (E) r;
592     }
593 
acquireConstSupplier(int type)594     static PooledLambdaImpl acquireConstSupplier(int type) {
595         PooledLambdaImpl r = acquire(PooledLambdaImpl.sPool);
596         int lambdaType = LambdaType.encode(LambdaType.MASK_ARG_COUNT, type);
597         r.setFlags(PooledLambdaImpl.MASK_FUNC_TYPE, lambdaType);
598         r.setFlags(PooledLambdaImpl.MASK_EXPOSED_AS, lambdaType);
599         return r;
600     }
601 
acquire(Pool pool)602     static PooledLambdaImpl acquire(Pool pool) {
603         PooledLambdaImpl r = pool.acquire();
604         if (r == null) r = new PooledLambdaImpl();
605         r.mFlags &= ~FLAG_RECYCLED;
606         r.setFlags(FLAG_ACQUIRED_FROM_MESSAGE_CALLBACKS_POOL,
607                 pool == sMessageCallbacksPool ? 1 : 0);
608         return r;
609     }
610 
setIfInBounds(Object[] array, int i, Object a)611     private static void setIfInBounds(Object[] array, int i, Object a) {
612         if (i < ArrayUtils.size(array)) array[i] = a;
613     }
614 
615     @Override
616     public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
negate()617             Object, Object, R> negate() {
618         throw new UnsupportedOperationException();
619     }
620 
621     @Override
622     public <V> OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
andThen(Function<? super R, ? extends V> after)623             Object, Object, V> andThen(Function<? super R, ? extends V> after) {
624         throw new UnsupportedOperationException();
625     }
626 
627     @Override
getAsDouble()628     public double getAsDouble() {
629         return Double.longBitsToDouble(mConstValue);
630     }
631 
632     @Override
getAsInt()633     public int getAsInt() {
634         return (int) mConstValue;
635     }
636 
637     @Override
getAsLong()638     public long getAsLong() {
639         return mConstValue;
640     }
641 
642     @Override
643     public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
recycleOnUse()644             Object, Object, R> recycleOnUse() {
645         if (DEBUG) Log.i(LOG_TAG, this + ".recycleOnUse()");
646         mFlags |= FLAG_RECYCLE_ON_USE;
647         return this;
648     }
649 
650     @Override
getTraceName()651     public String getTraceName() {
652         return FunctionalUtils.getLambdaName(mFunc);
653     }
654 
isRecycled()655     private boolean isRecycled() {
656         return (mFlags & FLAG_RECYCLED) != 0;
657     }
658 
isRecycleOnUse()659     private boolean isRecycleOnUse() {
660         return (mFlags & FLAG_RECYCLE_ON_USE) != 0;
661     }
662 
isInvocationArgAtIndex(int argIndex)663     private boolean isInvocationArgAtIndex(int argIndex) {
664         return (mFlags & (1 << argIndex)) != 0;
665     }
666 
getFlags(int mask)667     int getFlags(int mask) {
668         return unmask(mask, mFlags);
669     }
670 
setFlags(int mask, int value)671     void setFlags(int mask, int value) {
672         mFlags &= ~mask;
673         mFlags |= mask(mask, value);
674     }
675 
676     /**
677      * 0xFF000, 0xAB -> 0xAB000
678      */
mask(int mask, int value)679     private static int mask(int mask, int value) {
680         return (value << Integer.numberOfTrailingZeros(mask)) & mask;
681     }
682 
683     /**
684      * 0xFF000, 0xAB123 -> 0xAB
685      */
unmask(int mask, int bits)686     private static int unmask(int mask, int bits) {
687         return (bits & mask) / (1 << Integer.numberOfTrailingZeros(mask));
688     }
689 
690     /**
691      * Contract for encoding a supported lambda type in {@link #MASK_BIT_COUNT} bits
692      */
693     static class LambdaType {
694         public static final int MASK_ARG_COUNT = 0b1111;
695         public static final int MASK_RETURN_TYPE = 0b1110000;
696         public static final int MASK = MASK_ARG_COUNT | MASK_RETURN_TYPE;
697         public static final int MASK_BIT_COUNT = 7;
698 
encode(int argCount, int returnType)699         static int encode(int argCount, int returnType) {
700             return mask(MASK_ARG_COUNT, argCount) | mask(MASK_RETURN_TYPE, returnType);
701         }
702 
decodeArgCount(int type)703         static int decodeArgCount(int type) {
704             return type & MASK_ARG_COUNT;
705         }
706 
decodeReturnType(int type)707         static int decodeReturnType(int type) {
708             return unmask(MASK_RETURN_TYPE, type);
709         }
710 
toString(int type)711         static String toString(int type) {
712             int argCount = decodeArgCount(type);
713             int returnType = decodeReturnType(type);
714             if (argCount == 0) {
715                 if (returnType == ReturnType.VOID) return "Runnable";
716                 if (returnType == ReturnType.OBJECT || returnType == ReturnType.BOOLEAN) {
717                     return "Supplier";
718                 }
719             }
720             return argCountPrefix(argCount) + ReturnType.lambdaSuffix(returnType);
721         }
722 
argCountPrefix(int argCount)723         private static String argCountPrefix(int argCount) {
724             switch (argCount) {
725                 case MASK_ARG_COUNT: return "";
726                 case 0: return "";
727                 case 1: return "";
728                 case 2: return "Bi";
729                 case 3: return "Tri";
730                 case 4: return "Quad";
731                 case 5: return "Quint";
732                 case 6: return "Hex";
733                 case 7: return "Hept";
734                 case 8: return "Oct";
735                 case 9: return "Nona";
736                 case 10: return "Dec";
737                 case 11: return "Undec";
738                 default: return "" + argCount + "arg";
739             }
740         }
741 
742         static class ReturnType {
743             public static final int VOID = 1;
744             public static final int BOOLEAN = 2;
745             public static final int OBJECT = 3;
746             public static final int INT = 4;
747             public static final int LONG = 5;
748             public static final int DOUBLE = 6;
749 
toString(int returnType)750             static String toString(int returnType) {
751                 switch (returnType) {
752                     case VOID: return "VOID";
753                     case BOOLEAN: return "BOOLEAN";
754                     case OBJECT: return "OBJECT";
755                     case INT: return "INT";
756                     case LONG: return "LONG";
757                     case DOUBLE: return "DOUBLE";
758                     default: return "" + returnType;
759                 }
760             }
761 
lambdaSuffix(int type)762             static String lambdaSuffix(int type) {
763                 return prefix(type) + suffix(type);
764             }
765 
prefix(int type)766             private static String prefix(int type) {
767                 switch (type) {
768                     case INT: return "Int";
769                     case LONG: return "Long";
770                     case DOUBLE: return "Double";
771                     default: return "";
772                 }
773             }
774 
suffix(int type)775             private static String suffix(int type) {
776                 switch (type) {
777                     case VOID: return "Consumer";
778                     case BOOLEAN: return "Predicate";
779                     case OBJECT: return "Function";
780                     default: return "Supplier";
781                 }
782             }
783         }
784     }
785 }
786