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