1 /* 2 * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.util.stream; 26 27 import java.util.EnumMap; 28 import java.util.Map; 29 30 /** 31 * Flags corresponding to characteristics of streams and operations. Flags are utilized by the stream 32 * framework to control, specialize or optimize computation. 33 * 34 * <p> 35 * Stream flags may be used to describe characteristics of several different entities associated with streams: 36 * stream sources, intermediate operations, and terminal operations. Not all stream flags are meaningful for all 37 * entities; the following table summarizes which flags are meaningful in what contexts: 38 * <pre> 39 * DISTINCT SORTED ORDERED SIZED SHORT_CIRCUIT PARALLEL 40 * Stream source Y Y Y Y N Y 41 * Intermediate operation PCI PCI PCI PC PI PC 42 * Terminal operation N N PC N PI N 43 * </pre> 44 * 45 * <p>In the above table, "PCI" means "may preserve, clear, or inject"; "PC" means "may preserve or clear", 46 * "PI" means "may preserve or inject", and "N" means "not valid". 47 * 48 * <p>Stream flags are represented by unioned bit sets, so that a single word may describe all the 49 * characteristics of a given stream entity, and that, for example, the flags for a stream source can be 50 * efficiently combined with the flags for later operations on that stream. 51 * 52 * <p>The bit masks {@link #STREAM_MASK}, {@link #OP_MASK}, and {@link #TERMINAL_OP_MASK} can be ANDed with 53 * a bit set of stream flags to produce a mask containing only the valid flags for that entity type. 54 * 55 * <p>When describing a stream source, one only need describe what characteristics that stream has; when describing 56 * a stream operation, one need describe whether the operation preserves, injects, or clears that characteristic. 57 * Accordingly, two bits are used for each flag, so as to allow representing not only the presence of of a 58 * characteristic, but how an operation modifies that characteristic. There are two common forms in which 59 * flag bits are combined into an {@code int} bit set. <em>Stream flags</em> are a unioned bit set constructed by 60 * ORing the enum characteristic values of {@link #set()} (or, more commonly, ORing the corresponding static named 61 * constants prefixed with {@code IS_}). <em>Operation flags</em> are a unioned bit set constructed by 62 * ORing the enum characteristic values of {@link #set()} or {@link #clear()} (to inject, or clear, respectively, 63 * the corresponding flag), or more commonly ORing the corresponding named constants prefixed with {@code IS_} 64 * or {@code NOT_}. Flags that are not marked with {@code IS_} or {@code NOT_} are implicitly treated as preserved. 65 * Care must be taken when combining bitsets that the correct combining operations are applied in the correct order. 66 * 67 * <p> 68 * With the exception of {@link #PARALLEL}, stream characteristics can be derived from the equivalent 69 * {@link java.util.Spliterator} characteristics: {@link java.util.Spliterator#DISTINCT}, 70 * {@link java.util.Spliterator#SORTED}, {@link java.util.Spliterator#ORDERED}, and 71 * {@link java.util.Spliterator#SIZED}. A spliterator characteristics bit set can be converted to stream flags 72 * using the method {@link #fromCharacteristics(int)} and converted back using {@link #toCharacteristics(int)}. 73 * (The bit set {@link #SPLITERATOR_CHARACTERISTICS_MASK} is used to AND with a bit set to produce a valid 74 * spliterator characteristics bit set that can be converted to stream flags.) 75 * 76 * <p> 77 * The source of a stream encapsulates a spliterator. The characteristics of that source 78 * spliterator when transformed to stream flags will be a proper subset of stream flags of that stream. 79 * For example: 80 * <pre> {@code 81 * Spliterator s = ...; 82 * Stream stream = Streams.stream(s); 83 * flagsFromSpliterator = fromCharacteristics(s.characteristics()); 84 * assert(flagsFromSpliterator & stream.getStreamFlags() == flagsFromSpliterator); 85 * }</pre> 86 * 87 * <p> 88 * An intermediate operation, performed on an input stream to create a new output stream, 89 * may preserve, clear or inject stream or operation characteristics. 90 * Similarly, a terminal operation, performed on an input stream to produce an output result 91 * may preserve, clear or inject stream or operation characteristics. 92 * Preservation means that if that characteristic is present on the input, then it is 93 * also present on the output. Clearing means that the characteristic is not present on the output regardless 94 * of the input. Injection means that the characteristic is present on the output regardless of the input. 95 * If a characteristic is not cleared or injected then it is implicitly preserved. 96 * 97 * <p> 98 * A pipeline consists of a stream source encapsulating a spliterator, one or more intermediate operations, 99 * and finally a terminal operation that produces a result. At each stage of the pipeline, a combined 100 * stream and operation flags can be calculated, using {@link #combineOpFlags(int, int)}. 101 * Such flags ensure that preservation, clearing and injecting information is retained at each stage. 102 * 103 * The combined stream and operation flags for the source stage of the pipeline is calculated as 104 * follows: 105 * <pre> {@code 106 * int flagsForSourceStage = combineOpFlags(sourceFlags, INITIAL_OPS_VALUE); 107 * }</pre> 108 * 109 * The combined stream and operation flags of each subsequent intermediate operation stage in the pipeline is 110 * calculated as follows: 111 * <pre> {@code 112 * int flagsForThisStage = combineOpFlags(flagsForPreviousStage, thisOpFlags); 113 * }</pre> 114 * 115 * Finally the flags output from the last intermediate operation of the pipeline are combined with the operation flags 116 * of the terminal operation to produce the flags output from the pipeline. 117 * 118 * <p>Those flags can then be used to apply optimizations. For example, if {@code SIZED.isKnown(flags)} returns true 119 * then the stream size remains constant throughout the pipeline, this information can be utilized to pre-allocate data 120 * structures and combined with {@link java.util.Spliterator#SUBSIZED} that information can be utilized to perform 121 * concurrent in-place updates into a shared array. 122 * 123 * For specific details see the {@link AbstractPipeline} constructors. 124 * 125 * @since 1.8 126 */ 127 // @@@ When a new flag is added what should happen for existing operations? 128 // Need to move to a builder approach used by ops where the masks for the new flag are 129 // taken into account for default behaviour. 130 enum StreamOpFlag { 131 132 /* 133 * Each characteristic takes up 2 bits in a bit set to accommodate preserving, clearing and 134 * setting/injecting information. 135 * 136 * This applies to stream flags, intermediate/terminal operation flags, and combined stream and 137 * operation flags. Even though the former only requires 1 bit of information per characteristic, 138 * is it more efficient when combining flags to align set and inject bits. 139 * 140 * Characteristics belong to certain types, see the Type enum. Bit masks for the types are 141 * constructed as per the following table: 142 * 143 * DISTINCT SORTED ORDERED SIZED SHORT_CIRCUIT PARALLEL 144 * SPLITERATOR 01 01 01 01 00 00 145 * STREAM 01 01 01 01 00 01 146 * OP 11 11 11 10 01 10 147 * TERMINAL_OP 00 00 10 00 01 00 148 * UPSTREAM_TERMINAL_OP 00 00 10 00 00 00 149 * 150 * 01 = set/inject 151 * 10 = clear 152 * 11 = preserve 153 * 154 * Construction of the columns is performed using a simple builder for non-zero values. 155 */ 156 157 158 // The following flags correspond to characteristics on Spliterator 159 // and the values MUST be equal. 160 // 161 162 /** 163 * Characteristic value signifying that, for each pair of 164 * encountered elements in a stream {@code x, y}, {@code !x.equals(y)}. 165 * <p> 166 * A stream may have this value or an intermediate operation can preserve, clear or inject 167 * this value. 168 */ 169 // 0, 0x00000001 170 // Matches Spliterator.DISTINCT 171 DISTINCT(0, 172 set(Type.SPLITERATOR).set(Type.STREAM).setAndClear(Type.OP)), 173 174 /** 175 * Characteristic value signifying that encounter order follows a 176 * defined sort order. 177 * <p> 178 * A stream can have this value or an intermediate operation can preserve, clear or inject 179 * this value. 180 */ 181 // 1, 0x00000004 182 // Matches Spliterator.SORTED 183 SORTED(1, 184 set(Type.SPLITERATOR).set(Type.STREAM).setAndClear(Type.OP)), 185 186 /** 187 * Characteristic value signifying that an encounter order is 188 * defined for stream elements. 189 * <p> 190 * A stream can have this value, an intermediate operation can preserve, clear or inject 191 * this value, or a terminal operation can preserve or clear this value. 192 */ 193 // 2, 0x00000010 194 // Matches Spliterator.ORDERED 195 ORDERED(2, 196 set(Type.SPLITERATOR).set(Type.STREAM).setAndClear(Type.OP).clear(Type.TERMINAL_OP) 197 .clear(Type.UPSTREAM_TERMINAL_OP)), 198 199 /** 200 * Characteristic value signifying that size of the stream 201 * is of a known finite size that is equal to the known finite 202 * size of the source spliterator input to the first stream 203 * in the pipeline. 204 * <p> 205 * A stream can have this value or an intermediate operation can preserve or clear 206 * this value. 207 */ 208 // 3, 0x00000040 209 // Matches Spliterator.SIZED 210 SIZED(3, 211 set(Type.SPLITERATOR).set(Type.STREAM).clear(Type.OP)), 212 213 // The following Spliterator characteristics are not currently used but a 214 // gap in the bit set is deliberately retained to enable corresponding stream 215 // flags if//when required without modification to other flag values. 216 // 217 // 4, 0x00000100 INFINITE(4, ... 218 // 5, 0x00000400 NONNULL(5, ... 219 // 6, 0x00001000 IMMUTABLE(6, ... 220 // 7, 0x00004000 CONCURRENT(7, ... 221 // 8, 0x00010000 SUBSIZED(8, ...) 222 223 // The following 3 flags are currently undefined and a free for any further 224 // spliterator characteristics. 225 // 226 // 9, 0x00040000 227 // 10, 0x00100000 228 // 11, 0x00400000 229 230 // The following flags are specific to streams and operations 231 // 232 233 /** 234 * Characteristic value signifying that an operation may short-circuit the stream. 235 * <p> 236 * An intermediate operation can preserve or inject this value, 237 * or a terminal operation can preserve or inject this value. 238 */ 239 // 12, 0x01000000 240 SHORT_CIRCUIT(12, 241 set(Type.OP).set(Type.TERMINAL_OP)), 242 243 244 /** 245 * Characteristic value signifying that the stream is to be evaluated in parallel rather than 246 * sequentially. 247 * <p> 248 * A stream can have this value or an intermediate operation can preserve or clear 249 * this value. 250 */ 251 // 13, 0x04000000 252 PARALLEL(13, 253 set(Type.STREAM).clear(Type.OP)); 254 255 // The following 2 flags are currently undefined and a free for any further 256 // stream flags if/when required 257 // 258 // 14, 0x10000000 259 // 15, 0x40000000 260 261 /** 262 * Type of a flag 263 */ 264 enum Type { 265 /** The flag is associated with spliterator characteristics. */ 266 SPLITERATOR, 267 268 /** The flag is associated with stream flags. */ 269 STREAM, 270 271 /** The flag is associated with intermediate operation flags. */ 272 OP, 273 274 /** The flag is associated with terminal operation flags. */ 275 TERMINAL_OP, 276 277 /** 278 * The flag is associated with terminal operation flags that are propagated upstream 279 * across the last stateful operation boundary 280 */ 281 UPSTREAM_TERMINAL_OP 282 } 283 284 /** 285 * The bit pattern for setting/injecting a flag. 286 */ 287 private static final int SET_BITS = 0b01; 288 289 /** 290 * The bit pattern for clearing a flag. 291 */ 292 private static final int CLEAR_BITS = 0b10; 293 294 /** 295 * The bit pattern for preserving a flag. 296 */ 297 private static final int PRESERVE_BITS = 0b11; 298 299 private static MaskBuilder set(Type t) { 300 return new MaskBuilder(new EnumMap<>(Type.class)).set(t); 301 } 302 303 private static class MaskBuilder { 304 final Map<Type, Integer> map; 305 306 MaskBuilder(Map<Type, Integer> map) { 307 this.map = map; 308 } 309 310 MaskBuilder mask(Type t, Integer i) { 311 map.put(t, i); 312 return this; 313 } 314 315 MaskBuilder set(Type t) { 316 return mask(t, SET_BITS); 317 } 318 319 MaskBuilder clear(Type t) { 320 return mask(t, CLEAR_BITS); 321 } 322 323 MaskBuilder setAndClear(Type t) { 324 return mask(t, PRESERVE_BITS); 325 } 326 327 Map<Type, Integer> build() { 328 for (Type t : Type.values()) { 329 map.putIfAbsent(t, 0b00); 330 } 331 return map; 332 } 333 } 334 335 // The mask table for a flag, this is used to determine 336 // if a flag corresponds to a certain flag type and for creating 337 // mask constants. 338 private final Map<Type, Integer> maskTable; 339 340 // The bit position in the bit mask 341 private final int bitPosition; 342 343 // The set 2 bit set offset at the bit position 344 private final int set; 345 346 // The clear 2 bit set offset at the bit position 347 private final int clear; 348 349 // The preserve 2 bit set offset at the bit position 350 private final int preserve; 351 352 private StreamOpFlag(int position, MaskBuilder maskBuilder) { 353 this.maskTable = maskBuilder.build(); 354 // Two bits per flag 355 position *= 2; 356 this.bitPosition = position; 357 this.set = SET_BITS << position; 358 this.clear = CLEAR_BITS << position; 359 this.preserve = PRESERVE_BITS << position; 360 } 361 362 /** 363 * Get the bitmap associated with setting this characteristic 364 * @return the bitmap for setting this characteristic 365 */ 366 int set() { 367 return set; 368 } 369 370 /** 371 * Get the bitmap associated with clearing this characteristic 372 * @return the bitmap for clearing this characteristic 373 */ 374 int clear() { 375 return clear; 376 } 377 378 /** 379 * Is this flag a stream-based flag? 380 * 381 * @return true if a stream-based flag, otherwise false. 382 */ 383 boolean isStreamFlag() { 384 return maskTable.get(Type.STREAM) > 0; 385 } 386 387 /** 388 * Check if this flag is set on stream flags, injected on operation flags, 389 * and injected on combined stream and operation flags. 390 * 391 * @param flags the stream flags, operation flags, or combined stream and operation flags 392 * @return true if this flag is known, otherwise false. 393 */ 394 boolean isKnown(int flags) { 395 return (flags & preserve) == set; 396 } 397 398 /** 399 * Check if this flag is cleared on operation flags or combined stream and operation flags. 400 * 401 * @param flags the operation flags or combined stream and operations flags. 402 * @return true if this flag is preserved, otherwise false. 403 */ 404 boolean isCleared(int flags) { 405 return (flags & preserve) == clear; 406 } 407 408 /** 409 * Check if this flag is preserved on combined stream and operation flags. 410 * 411 * @param flags the combined stream and operations flags. 412 * @return true if this flag is preserved, otherwise false. 413 */ 414 boolean isPreserved(int flags) { 415 return (flags & preserve) == preserve; 416 } 417 418 /** 419 * 420 * @param t the flag type. 421 * @return true if this flag can be set for the flag type, otherwise false. 422 */ 423 boolean canSet(Type t) { 424 return (maskTable.get(t) & SET_BITS) > 0; 425 } 426 427 /** 428 * The bit mask for spliterator characteristics 429 */ 430 static final int SPLITERATOR_CHARACTERISTICS_MASK = createMask(Type.SPLITERATOR); 431 432 /** 433 * The bit mask for source stream flags. 434 */ 435 static final int STREAM_MASK = createMask(Type.STREAM); 436 437 /** 438 * The bit mask for intermediate operation flags. 439 */ 440 static final int OP_MASK = createMask(Type.OP); 441 442 /** 443 * The bit mask for terminal operation flags. 444 */ 445 static final int TERMINAL_OP_MASK = createMask(Type.TERMINAL_OP); 446 447 /** 448 * The bit mask for upstream terminal operation flags. 449 */ 450 static final int UPSTREAM_TERMINAL_OP_MASK = createMask(Type.UPSTREAM_TERMINAL_OP); 451 452 private static int createMask(Type t) { 453 int mask = 0; 454 for (StreamOpFlag flag : StreamOpFlag.values()) { 455 mask |= flag.maskTable.get(t) << flag.bitPosition; 456 } 457 return mask; 458 } 459 460 // Complete flag mask 461 private static final int FLAG_MASK = createFlagMask(); 462 463 private static int createFlagMask() { 464 int mask = 0; 465 for (StreamOpFlag flag : StreamOpFlag.values()) { 466 mask |= flag.preserve; 467 } 468 return mask; 469 } 470 471 // Flag mask for stream flags that are set 472 private static final int FLAG_MASK_IS = STREAM_MASK; 473 474 // Flag mask for stream flags that are cleared 475 private static final int FLAG_MASK_NOT = STREAM_MASK << 1; 476 477 /** 478 * The initial value to be combined with the stream flags of the first stream in the pipeline. 479 */ 480 static final int INITIAL_OPS_VALUE = FLAG_MASK_IS | FLAG_MASK_NOT; 481 482 /** 483 * The bit value to set or inject {@link #DISTINCT} 484 */ 485 static final int IS_DISTINCT = DISTINCT.set; 486 487 /** 488 * The bit value to clear {@link #DISTINCT} 489 */ 490 static final int NOT_DISTINCT = DISTINCT.clear; 491 492 /** 493 * The bit value to set or inject {@link #SORTED} 494 */ 495 static final int IS_SORTED = SORTED.set; 496 497 /** 498 * The bit value to clear {@link #SORTED} 499 */ 500 static final int NOT_SORTED = SORTED.clear; 501 502 /** 503 * The bit value to set or inject {@link #ORDERED} 504 */ 505 static final int IS_ORDERED = ORDERED.set; 506 507 /** 508 * The bit value to clear {@link #ORDERED} 509 */ 510 static final int NOT_ORDERED = ORDERED.clear; 511 512 /** 513 * The bit value to set {@link #SIZED} 514 */ 515 static final int IS_SIZED = SIZED.set; 516 517 /** 518 * The bit value to clear {@link #SIZED} 519 */ 520 static final int NOT_SIZED = SIZED.clear; 521 522 /** 523 * The bit value to inject {@link #SHORT_CIRCUIT} 524 */ 525 static final int IS_SHORT_CIRCUIT = SHORT_CIRCUIT.set; 526 527 /** 528 * The bit value to set {@link #PARALLEL} 529 */ 530 static final int IS_PARALLEL = PARALLEL.set; 531 532 /** 533 * The bit value to clear {@link #PARALLEL} 534 */ 535 static final int NOT_PARALLEL = PARALLEL.clear; 536 537 private static int getMask(int flags) { 538 return (flags == 0) 539 ? FLAG_MASK 540 : ~(flags | ((FLAG_MASK_IS & flags) << 1) | ((FLAG_MASK_NOT & flags) >> 1)); 541 } 542 543 /** 544 * Combine stream or operation flags with previously combined stream and operation flags to 545 * produce updated combined stream and operation flags. 546 * <p> 547 * A flag set on stream flags or injected on operation flags, 548 * and injected combined stream and operation flags, 549 * will be injected on the updated combined stream and operation flags. 550 * </p> 551 * <p> 552 * A flag set on stream flags or injected on operation flags, 553 * and cleared on the combined stream and operation flags, 554 * will be cleared on the updated combined stream and operation flags. 555 * </p> 556 * <p> 557 * A flag set on the stream flags or injected on operation flags, 558 * and preserved on the combined stream and operation flags, 559 * will be injected on the updated combined stream and operation flags. 560 * </p> 561 * <p> 562 * A flag not set on the stream flags or cleared/preserved on operation flags, 563 * and injected on the combined stream and operation flags, 564 * will be injected on the updated combined stream and operation flags. 565 * </p> 566 * <p> 567 * A flag not set on the stream flags or cleared/preserved on operation flags, 568 * and cleared on the combined stream and operation flags, 569 * will be cleared on the updated combined stream and operation flags. 570 * </p> 571 * <p> 572 * A flag not set on the stream flags, 573 * and preserved on the combined stream and operation flags 574 * will be preserved on the updated combined stream and operation flags. 575 * </p> 576 * <p> 577 * A flag cleared on operation flags, 578 * and preserved on the combined stream and operation flags 579 * will be cleared on the updated combined stream and operation flags. 580 * </p> 581 * <p> 582 * A flag preserved on operation flags, 583 * and preserved on the combined stream and operation flags 584 * will be preserved on the updated combined stream and operation flags. 585 * </p> 586 * 587 * @param newStreamOrOpFlags the stream or operation flags. 588 * @param prevCombOpFlags previously combined stream and operation flags. 589 * The value {#link INITIAL_OPS_VALUE} must be used as the seed value. 590 * @return the updated combined stream and operation flags. 591 */ 592 static int combineOpFlags(int newStreamOrOpFlags, int prevCombOpFlags) { 593 // 0x01 or 0x10 nibbles are transformed to 0x11 594 // 0x00 nibbles remain unchanged 595 // Then all the bits are flipped 596 // Then the result is logically or'ed with the operation flags. 597 return (prevCombOpFlags & StreamOpFlag.getMask(newStreamOrOpFlags)) | newStreamOrOpFlags; 598 } 599 600 /** 601 * Convert combined stream and operation flags to stream flags. 602 * 603 * <p> Each flag injected on the combined stream and operation flags will be set on the stream flags. 604 * 605 * @param combOpFlags the combined stream and operation flags. 606 * @return the stream flags. 607 */ 608 static int toStreamFlags(int combOpFlags) { 609 // By flipping the nibbles 0x11 become 0x00 and 0x01 become 0x10 610 // Shift left 1 to restore set flags and mask off anything other than the set flags 611 return ((~combOpFlags) >> 1) & FLAG_MASK_IS & combOpFlags; 612 } 613 614 /** 615 * Convert stream flags to a spliterator characteristic bit set. 616 * 617 * @param streamFlags the stream flags. 618 * @return the spliterator characteristic bit set. 619 */ 620 static int toCharacteristics(int streamFlags) { 621 return streamFlags & SPLITERATOR_CHARACTERISTICS_MASK; 622 } 623 624 /** 625 * Convert a spliterator characteristic bit set to stream flags. 626 * 627 * @param characteristics the spliterator characteristic bit set. 628 * @return the stream flags. 629 */ 630 static int fromCharacteristics(int characteristics) { 631 return characteristics & SPLITERATOR_CHARACTERISTICS_MASK; 632 } 633 }