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