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